// Guest address -> host function lookup for indirect branches (rt_dispatch, declared in cpu.h). // // One flat table covers every module's code range: slot (pc - lo) >> 2 holds the host function for a guest // function start, as a 32-bit offset from an anchor address. Lookup is one range check and one load. The table is // built once by rt_dispatch_init and never written again, so threads read it without locks. #pragma once #include #include #include "cpu.h" // A lifted module: its place in the guest layout and the generator's sorted function table. typedef struct RtModule { const char *name; uint64_t base, size; // guest image (layout.h MOD__BASE / _SIZE) const uint64_t *addrs; // _fn_addrs: guest function starts, strictly ascending const GuestFn *fns; // _fn_ptrs: the lifted function for each start uint64_t count; // _fn_count } RtModule; // The module glue that tools/build_game.py writes for each build (build//modules.c), from layout.json and // layout.h: every module of the layout, and the modules linked into this executable. typedef struct RtLayoutEntry { const char *name; uint64_t base, size; } RtLayoutEntry; extern const RtLayoutEntry rt_layout[]; extern const int rt_layout_count; int rt_linked_modules(RtModule *out, int max); // Register a host function at a guest address outside every module (HLE entry points). Allowed only before // rt_dispatch_init; the registry is fixed afterwards. void rt_register_host(uint64_t addr, GuestFn fn); // Build the table from the modules (kept by pointer; they must outlive the process). Call it once, before any guest // thread starts: thread creation publishes the table to the threads. Fatal on a malformed table: // unsorted or duplicate starts, a start outside its module, overlapping modules, host code spread over 4 GiB. void rt_dispatch_init(const RtModule *mods, int count); // The host function for a guest address, or NULL when nothing is there. Does not run guest code. GuestFn rt_dispatch_lookup(uint64_t pc); // "0x7000001234 (main+0x1234)" for a guest address inside a module, else the bare address. Returns buf. const char *rt_guest_name(uint64_t pc, char *buf, int size); typedef struct RtDispatchStats { uint64_t lo, hi; // guest range the table covers uint64_t slots; // (hi - lo) / 4 uint64_t table_bytes; // reserved for the table uint64_t functions; // filled slots uint64_t host_fns; // rt_register_host entries } RtDispatchStats; RtDispatchStats rt_dispatch_stats(void); // Runtime fatal error: message to stderr, then exit. Used by the dispatcher and the stubs. void rt_fatal(const char *fmt, ...) __attribute__((noreturn, format(printf, 1, 2)));