# MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI) # RUMPK CORE // FIBER (Unified Multi-Arch) # The atom of execution. # # Supported Architectures: # - aarch64 (ARM64): VisionFive 2, RPi, AWS Graviton # - amd64 (x86_64): Standard servers, trading systems # - riscv64 (RISC-V): Sovereign compute, satellites {.push stackTrace: off, lineTrace: off.} # ========================================================= # Architecture-Specific Constants # ========================================================= when defined(amd64) or defined(x86_64): const CONTEXT_SIZE = 56 const RET_ADDR_INDEX = 6 # RIP at [sp + 48] const ARCH_NAME = "x86_64" elif defined(arm64) or defined(aarch64): const CONTEXT_SIZE = 96 const RET_ADDR_INDEX = 11 # x30 (LR) at [sp + 88] const ARCH_NAME = "aarch64" elif defined(riscv64): const CONTEXT_SIZE = 112 const RET_ADDR_INDEX = 0 # ra at [sp + 0] const ARCH_NAME = "riscv64" else: {.error: "Unsupported architecture for Rumpk fibers".} # ========================================================= # Types # ========================================================= type FiberState* = object sp*: uint64 # The Stack Pointer (Must be first field!) entry*: proc() {.cdecl.} # Entry point for this fiber Fiber* = ptr FiberObject FiberObject* = object id*: uint64 name*: cstring state*: FiberState stack*: ptr UncheckedArray[uint8] stack_size*: int # ========================================================= # Imports # ========================================================= # Import the Assembly Magic (same symbol name, different implementation per arch) proc cpu_switch_to(prev_sp_ptr: ptr uint64, next_sp: uint64) {.importc, cdecl.} # Import console for debugging proc console_write(p: pointer, len: csize_t) {.importc, cdecl.} proc debug*(s: string) = if s.len > 0: console_write(unsafeAddr s[0], csize_t(s.len)) proc print_arch_info*() = debug("[Rumpk] Architecture Context: " & ARCH_NAME & "\n") # ========================================================= # Constants # ========================================================= const STACK_SIZE* = 4096 # ========================================================= # Fiber State # ========================================================= var main_fiber: FiberObject var current_fiber*: Fiber = addr main_fiber # ========================================================= # Trampoline (Entry point for new fibers) # ========================================================= proc fiber_trampoline() {.cdecl, exportc, noreturn.} = var msg = "[FIBER] Trampoline Entry!\n" console_write(addr msg[0], csize_t(msg.len)) let f = current_fiber if f.state.entry != nil: f.state.entry() # If the fiber returns, halt when defined(amd64) or defined(x86_64): while true: {.emit: "asm volatile(\"hlt\");".} elif defined(arm64) or defined(aarch64): while true: {.emit: "asm volatile(\"wfi\");".} elif defined(riscv64): while true: {.emit: "asm volatile(\"wfi\");".} # ========================================================= # Fiber Initialization (Arch-Specific) # ========================================================= proc init_fiber*(f: Fiber, entry: proc() {.cdecl.}, stack_base: pointer) = f.state.entry = entry # Start at top of stack var sp = cast[uint64](stack_base) + STACK_SIZE # 1. Align to 16 bytes (Universal requirement) sp = sp and not 15'u64 # 2. Reserve space for the context frame sp = sp - CONTEXT_SIZE # 3. Setup the Context (zero all, set return address) var stack_ptr = cast[ptr UncheckedArray[uint64]](sp) # Zero out the frame let num_regs = CONTEXT_SIZE div 8 for i in 0..