< [Back](chapter-15.md) | [Summary](table-of-contents.md) > # **Host ABI and Syscalls** This chapter defines the Application Binary Interface (ABI) between the Prometeu Virtual Machine (PVM) and the host environment. It specifies how syscalls are encoded, invoked, verified, and accounted for. Syscalls provide controlled access to host-managed subsystems such as graphics, audio, input, asset banks, and persistent storage. This chapter defines the **contract**. Individual subsystems (GFX, AUDIO, MEMCARD, ASSETS, etc.) define their own syscall tables that conform to this ABI. --- ## 1 Design Principles The syscall system follows these rules: 1. **Deterministic**: Syscalls must behave deterministically for the same inputs and frame state. 2. **Synchronous**: Syscalls execute to completion within the current VM slice. 3. **Non-blocking**: Long operations must be modeled as request + status polling. 4. **Capability-gated**: Each syscall requires a declared capability. 5. **Stack-based ABI**: Arguments and return values are passed via VM slots. 6. **Not first-class**: Syscalls are callable but cannot be stored as values. --- ## 2 Syscall Instruction Semantics The VM provides a single instruction: ``` SYSCALL ``` Where: * `` is a 32-bit integer identifying the syscall. Execution steps: 1. The VM looks up the syscall metadata using ``. 2. The VM verifies that enough arguments exist on the stack. 3. The VM checks capability requirements. 4. The syscall executes in the host environment. 5. The syscall leaves exactly `ret_slots` values on the stack. If any contract rule is violated, the VM traps. --- ## 3 Syscall Metadata Table Each syscall is defined by a metadata entry. ### SyscallMeta structure ``` SyscallMeta { id: u32 name: string arg_slots: u8 ret_slots: u8 capability: CapabilityId may_allocate: bool cost_hint: u32 } ``` Fields: | Field | Description | | -------------- | ------------------------------------------------ | | `id` | Unique syscall identifier | | `name` | Human-readable name | | `arg_slots` | Number of input stack slots | | `ret_slots` | Number of return stack slots | | `capability` | Required capability | | `may_allocate` | Whether the syscall may allocate VM heap objects | | `cost_hint` | Expected cycle cost (for analysis/profiling) | The verifier uses this table to validate stack effects. --- ## 4 Arguments and Return Values Syscalls use the same slot-based ABI as functions. ### Argument passing Arguments are pushed onto the stack before the syscall. Example: ``` push a push b SYSCALL X // expects 2 arguments ``` ### Return values After execution, the syscall leaves exactly `ret_slots` values on the stack. Example: ``` // before: [] SYSCALL input_state // after: [held, pressed, released] ``` ### Slot types Each slot contains one of the VM value types: * int * bool * float * handle * null Composite return values are represented as multiple slots (stack tuples). --- ## 5 Syscalls as Callable Entities (Not First-Class) Syscalls behave like functions in terms of arguments and return values, but they are **not first-class values**. This means: * Syscalls can be invoked. * Syscalls cannot be stored in variables. * Syscalls cannot be passed as arguments. * Syscalls cannot be returned from functions. Only user-defined functions and closures are first-class. ### Example declaration (conceptual) ``` host fn input_state() -> (int, int, int) ``` This represents a syscall with three return values, but it cannot be treated as a function value. --- ## 6 Error Model: Traps vs Status Codes Syscalls use a hybrid error model. ### Trap conditions (contract violations) The VM traps when: * The syscall id is invalid. * The required capability is missing. * The stack does not contain enough arguments. * A handle is invalid or dead. These are considered fatal contract violations. ### Status returns (domain conditions) Normal operational states are returned as values. Examples: * asset not yet loaded * audio voice unavailable * memcard full These are represented by status codes in return slots. --- ## 7 Capability System Each syscall requires a capability. Capabilities are declared by the cartridge manifest. Example capability groups: * `gfx` * `audio` * `input` * `asset` * `memcard` If a syscall is invoked without the required capability: * The VM traps. --- ## 8 Interaction with the Garbage Collector The VM heap is managed by the GC. Host-managed memory is separate. ### Heap vs host memory | Memory | Managed by | GC scanned | | --------------- | ---------- | ---------- | | VM heap objects | VM GC | Yes | | Asset banks | Host | No | | Audio buffers | Host | No | | Framebuffers | Host | No | Assets are addressed by identifiers, not VM heap handles. ### Host root rule If a syscall stores a handle to a VM heap object beyond the duration of the call, it must register that handle as a **host root**. This prevents the GC from collecting objects still in use by the host. This rule applies only to VM heap objects (such as closures or user objects), not to asset identifiers or primitive values. --- ## 9 Determinism Rules Syscalls must obey deterministic execution rules. Forbidden behaviors: * reading real-time clocks * accessing non-deterministic OS APIs * performing blocking I/O Allowed patterns: * frame-based timers * request + poll status models * event delivery at frame boundaries --- ## 10 Cost Model and Budgeting Each syscall contributes to frame cost. The VM tracks: * cycles spent in syscalls * syscall counts * allocation cost (if any) Example telemetry: ``` Frame 10231: Syscalls: 12 Cycles (syscalls): 380 Allocations via syscalls: 2 ``` Nothing is free. --- ## 11 Blocking and Long Operations Syscalls must not block. Long operations must use a two-phase model: 1. Request 2. Status polling or event notification Example pattern: ``` asset.load(id) ... status, progress = asset.status(id) ``` --- ## 12 Summary * Syscalls are deterministic, synchronous, and non-blocking. * They use the same slot-based ABI as functions. * They are callable but not first-class. * Capabilities control access to host subsystems. * GC only manages VM heap objects. * Host-held heap objects must be registered as roots. * All syscall costs are tracked per frame. < [Back](chapter-15.md) | [Summary](table-of-contents.md) >