Thanks to visit codestin.com
Credit goes to github.com

Skip to content

libriscv/libloong

Repository files navigation

64-bit LoongArch sandboxing library

A high-performance LoongArch userspace emulator library designed for embedding and scripting applications.

Built on the proven architecture of libriscv, libloong has competitive interpreter performance while maintaining a compact ~18k line codebase.

For discussions & help, visit Discord.

Features

  • Fast LoongArch interpreter with optional JIT
  • Ultra-low latency call overheads
  • Support for 64-bit LoongArch (LA64)
  • Support for vector LSX and LASX instructions
  • C++ API with Rust and Go bindings
  • Zero dependencies
  • Execution timeout and memory safety
  • First-class pause/resume support

Design

Game engine scripting is where libloong excels. Traditional games expose modding through shared libraries (full system access), embedded VMs like Lua (~150ns call overhead), or Java run-times. libloong has ~4ns call overhead.

t

See the example Asteroid game.

Building

CMake configuration options:

  • LA_DEBUG=ON/OFF - Enable debug output (default: OFF)
  • LA_BINARY_TRANSLATION=ON/OFF - Enable binary translation (default: OFF)
  • LA_THREADED=ON/OFF - Enable threaded bytecode dispatch (default: ON)
  • LA_MASKED_MEMORY_BITS=N - Set masked memory arena size to 2^N bytes (0 = disabled, default: 0)

Example with options:

cmake .. -DCMAKE_BUILD_TYPE=Release \
         -DLA_MASKED_MEMORY_BITS=32 \
         -DLA_BINARY_TRANSLATION=ON
make -j6

Quick Start

#include <libloong/machine.hpp>

int main() {
    // Load a LoongArch ELF binary
    std::vector<uint8_t> binary = load_file("program.elf");

    // Create a machine with 64MB memory
    loongarch::Machine machine { binary, {
        .memory_max = 64 * 1024 * 1024
    }};

    // Setup program arguments
    machine.setup_linux({"program"}, {"LC_ALL=C"});

    // Run the program
    machine.simulate();
}

Performance

STREAM memory benchmark:

Function    Best Rate MB/s  Avg time     Min time     Max time
Copy:           33207.4     0.004963     0.004818     0.005065
Scale:          19829.5     0.008118     0.008069     0.008371
Add:            30967.6     0.007800     0.007750     0.007992
Triad:          29549.5     0.008258     0.008122     0.008415

There is a also a STREAM-like benchmark written in Rust in the examples:

Fill 76.3 MiB rate 27.9 GB/s | time min 2.9ms avg 3.1ms max 3.3ms
Copy 153 MiB  rate 35.3 GB/s | time min 4.5ms avg 4.6ms max 5.0ms
Scale 153 MiB rate 23.0 GB/s | time min 7.0ms avg 7.0ms max 7.1ms
Add 229 MiB   rate 31.9 GB/s | time min 7.5ms avg 7.6ms max 7.7ms
Triad 229 MiB rate 11.1 GB/s | time min 21.5ms avg 21.6ms max 21.8ms
CoreMark 1 0 interpreters, Dec 2025 (Ryzen 7950X)

Register machines still stand strongest at the end of 2025. libloong is currently the fastest 64-bit interpreter, reliably reaching 3000+ CoreMark score.

The lightweight JIT reaches 38% of native performance (15.5k vs 41k CoreMark) with full feature parity to the interpreter:

CoreMark 1.0 : 15580.375613 / GCC14.2.0 -O3 -DPERFORMANCE_RUN=1 / Static

Using embedded binary translation, it's currently possible to reach ~75% of native:

CoreMark 1.0 : 30730.418251 / GCC14.2.0 -O3 -DPERFORMANCE_RUN=1 / Static

.. however more work is needed to reach full potential. The upper bound for embedded binary translation should be around ~90% of native.

Documentation