Download Game! Currently 72 players and visitors. Last logged in:JosimDealRauskisPere

Blitzer's Blog >> 71841

Back to blogs index
Posted: 29 Aug 2026 20:40 [ permalink ]
Here is the complete, runnable JavaScript execution loop.
To make this genuinely isomorphic and prepare it for translation to C/x86, we
use JavaScript TypedArrays (Uint32Array and Int32Array). This forces the JS
engine (like V8) to lay out the memory exactly as a bare-metal kernel would,
and ensures our bitwise math perfectly mimics hardware CPU decoding.
The MVP Execution Engine
class LPCVirtualMachine {
    constructor(bytecode, constantPool, ivt) {
        // The Bytecode Segment (Fixed 32-bit instructions)
        this.bytecode = new Uint32Array(bytecode);
        
        // The Host Environment Links
        this.constantPool = constantPool;
        this.ivt = ivt;
        
        // The CPU State
        this.registers = new Int32Array(8); // R0 through R7
        this.ip = 0;                        // Instruction Pointer
        this.running = true;
    }

    // The core Fetch-Decode-Execute loop
    run() {
        while (this.running && this.ip < this.bytecode.length) {
            
            // 1. FETCH
            const inst = this.bytecode[this.ip++];

            // 2. DECODE
            // We use >>> (unsigned right shift) to prevent JavaScript 
            // from treating the highest bit as a negative sign.
            const opcode = (inst >>> 24) & 0xFF;
            const dest   = (inst >>> 20) & 0x0F;
            const src    = (inst >>> 16) & 0x0F;
            const imm    = inst & 0xFFFF;

            // 3. EXECUTE
            switch (opcode) {
                
                case 0x01: // LOAD_CONST
                    // In a full engine, this creates a Tagged Pointer.
                    // For the MVP, we just load the Constant Pool Index.
                    this.registers[dest] = imm;
                    break;

                case 0x15: // SYSCALL
                    // The ABI dictates R1 is the first argument.
                    const sys_routine = this.ivt[imm];
                    
                    if (sys_routine) {
                        // Pass the arg and the VM context to the Host,
                        // save the return value in the Destination Register
(R0).
                        this.registers[dest] = sys_routine(this.registers[1],
this);
                    } else {
                        throw new Error(`Kernel Panic: Unregistered SYSCALL
${imm}`);
                    }
                    break;

                case 0x0F: // RETURN
                    // Pop the shadow stack. Since this is the top level, we
halt.
                    this.running = false;
                    break;

                default:
                    throw new Error(`Kernel Panic: Unknown Opcode
0x${opcode.toString(16)}`);
            }
        }
    }
}

The Host Implementation (Mocking Mesh OS / V8)
Now we instantiate the Host environment. We provide the Constant Pool
(representing our String Ledger) and the Interrupt Vector Table (mapping Efun
IDs to native JS functions).
const constantPool = [
    "Hello HAUKI!" // Index 0
];

const bytecode = [
    0x01100000, // LOAD_CONST R1, 0
    0x15000001, // SYSCALL R0, 1 (write)
    0x0F000000  // RETURN
];

const ivt = {
    // Syscall ID 1: write()
    1: function efun_write(arg1_handle, vm) {
        // The host resolves the Handle (index) to actual memory/data
        const stringData = vm.constantPool[arg1_handle];
        
        // Output to the host console (or HAUKI-X86 VGA buffer)
        console.log(`[LPC Output] : ${stringData}`);
        
        return 0; // Return success to R0
    }
};

console.log("Booting HAUKI LPC VM...");
const vm = new LPCVirtualMachine(bytecode, constantPool, ivt);
vm.run();
console.log("VM Halted Safely. R0 (Accumulator) =", vm.registers[0]);

Why this architecture is brilliant for your goals:
 * Perfect Bitwise Mapping: The decoding logic ((inst >>> 24) & 0xFF) is
identical to how you would write an instruction decoder in C, or how an
FPGA/x86 CPU decodes opcodes. You are working at the true machine level, just
visualized in JS.
 * Absolute Host Isolation: The VM object has no access to console.log, the
DOM, or Node's fs module. It is utterly trapped. It can only interact with the
world if the Host explicitly registers a function in the ivt.
 * The Handle Magic: Notice how the VM never touches the string "Hello
HAUKI!". It just moves the integer 0 from the instruction payload into R1, and
then hands 0 back to the Host during the SYSCALL. The VM is blissfully
ignorant of memory allocation.
You now have a working, executing, isomorphic 32-bit register VM prototype.