/* AVM ISA v1 — C Port (Strict Functional Execution) */ #include #include #include #include /* ── Constants ─────────────────────────────────────────────── */ #define AVM_CLAMP_MIN (-2147483647) #define AVM_CLAMP_MAX 2147483647 #define AVM_Q0_MIN (-32767) #define AVM_Q0_MAX 32767 #define Q16_SCALE 65536 #define AVM_MAX_STACK 1024 #define AVM_MAX_LOCALS 256 /* ── Clamp ─────────────────────────────────────────────────── */ static inline int32_t avm_clamp(int64_t x) { if (x > AVM_CLAMP_MAX) return AVM_CLAMP_MAX; if (x < AVM_CLAMP_MIN) return AVM_CLAMP_MIN; return (int32_t)x; } static inline int32_t avm_q0_clamp(int64_t x) { if (x > AVM_Q0_MAX) return AVM_Q0_MAX; if (x < AVM_Q0_MIN) return AVM_Q0_MIN; return (int32_t)x; } /* Floor division matching Lean Int.ediv (rounds toward -inf) */ static inline int32_t floor_div(int64_t a, int64_t b) { if (b == 0) return 0; int64_t q = a / b; int64_t r = a % b; if (r != 0 && ((a ^ b) < 0)) q--; return (int32_t)q; } static inline bool lt_q16_v6(int32_t a, int32_t b) { bool sa = a < 0, sb = b < 0; return (sa != sb) ? sa : (a < b); } /* ── Types ─────────────────────────────────────────────────── */ typedef enum { TY_Q0, TY_Q16, TY_BOOL } AvmTy; typedef struct { AvmTy ty; union { int32_t i; bool b; } val; } AnyVal; /* ── Instructions ──────────────────────────────────────────── */ typedef enum { OP_PUSH_Q16, OP_PUSH_BOOL, OP_PUSH_Q0, OP_POP, OP_DUP, OP_SWAP, OP_LOAD, OP_STORE, OP_JUMP, OP_JUMP_IF, OP_PRIM, OP_HALT } OpCode; typedef enum { PRIM_ADD_Q0, PRIM_SUB_Q0, PRIM_ADD_Q16, PRIM_SUB_Q16, PRIM_MUL_Q16, PRIM_DIV_Q16, PRIM_LT_Q16, PRIM_EQ_Q16, PRIM_AND, PRIM_OR, PRIM_NOT } PrimCode; typedef struct { OpCode op; int32_t arg; bool arg2; } Instr; /* ── State ─────────────────────────────────────────────────── */ typedef struct { int pc; AnyVal stack[AVM_MAX_STACK]; int sp; AnyVal locals[AVM_MAX_LOCALS]; bool local_set[AVM_MAX_LOCALS]; bool halted; } State; void init_state(State *s, int n_locals) { s->pc = 0; s->sp = 0; s->halted = false; for (int i = 0; i < n_locals && i < AVM_MAX_LOCALS; i++) s->local_set[i] = false; } /* ── Primitive execution ───────────────────────────────────── */ AnyVal eval_prim(PrimCode p, AnyVal a, AnyVal b) { AnyVal r = { .ty = TY_Q0, .val.i = 0 }; if (p == PRIM_ADD_Q0) { if (a.ty != TY_Q0 || b.ty != TY_Q0) return r; r.ty = TY_Q0; r.val.i = avm_q0_clamp((int64_t)a.val.i + b.val.i); } else if (p == PRIM_SUB_Q0) { if (a.ty != TY_Q0 || b.ty != TY_Q0) return r; r.ty = TY_Q0; r.val.i = avm_q0_clamp((int64_t)a.val.i - b.val.i); } else if (p == PRIM_ADD_Q16) { if (a.ty != TY_Q16 || b.ty != TY_Q16) return r; r.ty = TY_Q16; r.val.i = avm_clamp((int64_t)a.val.i + b.val.i); } else if (p == PRIM_SUB_Q16) { if (a.ty != TY_Q16 || b.ty != TY_Q16) return r; r.ty = TY_Q16; r.val.i = avm_clamp((int64_t)a.val.i - b.val.i); } else if (p == PRIM_MUL_Q16) { if (a.ty != TY_Q16 || b.ty != TY_Q16) return r; r.ty = TY_Q16; r.val.i = avm_clamp(floor_div((int64_t)a.val.i * b.val.i, Q16_SCALE)); } else if (p == PRIM_DIV_Q16) { if (a.ty != TY_Q16 || b.ty != TY_Q16 || b.val.i == 0) return r; r.ty = TY_Q16; r.val.i = avm_clamp(floor_div((int64_t)a.val.i * Q16_SCALE, b.val.i)); } else if (p == PRIM_LT_Q16) { if (a.ty != TY_Q16 || b.ty != TY_Q16) return r; r.ty = TY_BOOL; r.val.b = lt_q16_v6(a.val.i, b.val.i); } else if (p == PRIM_EQ_Q16) { if (a.ty != TY_Q16 || b.ty != TY_Q16) return r; r.ty = TY_BOOL; r.val.b = (a.val.i == b.val.i); } else if (p == PRIM_AND) { if (a.ty != TY_BOOL || b.ty != TY_BOOL) return r; r.ty = TY_BOOL; r.val.b = a.val.b && b.val.b; } else if (p == PRIM_OR) { if (a.ty != TY_BOOL || b.ty != TY_BOOL) return r; r.ty = TY_BOOL; r.val.b = a.val.b || b.val.b; } else if (p == PRIM_NOT) { if (a.ty != TY_BOOL) return r; r.ty = TY_BOOL; r.val.b = !a.val.b; } return r; } /* ── Step ──────────────────────────────────────────────────── */ int step(State *s, const Instr *prog, int prog_len) { if (s->halted) return -1; if (s->pc < 0 || s->pc >= prog_len) { s->halted = true; return 0; } Instr instr = prog[s->pc]; int npc = s->pc + 1; /* Check stack depth for growing ops */ if (instr.op <= OP_PUSH_Q0 || instr.op == OP_DUP || instr.op == OP_LOAD) { if (s->sp >= AVM_MAX_STACK) return -2; /* stack overflow */ } if (instr.op == OP_PUSH_Q16) { s->stack[s->sp].ty = TY_Q16; s->stack[s->sp].val.i = avm_clamp(instr.arg); s->sp++; } else if (instr.op == OP_PUSH_BOOL) { s->stack[s->sp].ty = TY_BOOL; s->stack[s->sp].val.b = instr.arg2; s->sp++; } else if (instr.op == OP_PUSH_Q0) { s->stack[s->sp].ty = TY_Q0; s->stack[s->sp].val.i = avm_q0_clamp(instr.arg); s->sp++; } else if (instr.op == OP_POP) { if (s->sp <= 0) return -3; /* empty stack */ s->sp--; } else if (instr.op == OP_DUP) { if (s->sp <= 0) return -3; s->stack[s->sp] = s->stack[s->sp - 1]; s->sp++; } else if (instr.op == OP_SWAP) { if (s->sp < 2) return -4; /* underflow */ AnyVal tmp = s->stack[s->sp - 1]; s->stack[s->sp - 1] = s->stack[s->sp - 2]; s->stack[s->sp - 2] = tmp; } else if (instr.op == OP_LOAD) { int i = instr.arg; if (i < 0 || i >= AVM_MAX_LOCALS || !s->local_set[i]) return -5; /* missing local */ s->stack[s->sp] = s->locals[i]; s->sp++; } else if (instr.op == OP_STORE) { if (s->sp <= 0) return -3; int i = instr.arg; if (i < 0 || i >= AVM_MAX_LOCALS) return -5; s->locals[i] = s->stack[--s->sp]; s->local_set[i] = true; } else if (instr.op == OP_JUMP) { if (instr.arg < 0 || instr.arg >= prog_len) return -6; /* jump OOB */ npc = instr.arg; } else if (instr.op == OP_JUMP_IF) { if (s->sp <= 0) return -3; AnyVal v = s->stack[--s->sp]; if (v.ty != TY_BOOL) return -7; /* type mismatch */ if (v.val.b) { if (instr.arg < 0 || instr.arg >= prog_len) return -6; npc = instr.arg; } } else if (instr.op == OP_PRIM) { PrimCode p = (PrimCode)instr.arg; int arity = (p == PRIM_NOT) ? 1 : 2; if (s->sp < arity) return -4; AnyVal b = (arity >= 2) ? s->stack[--s->sp] : (AnyVal){0}; AnyVal a = s->stack[--s->sp]; /* Check division by zero before calling eval_prim */ if (p == PRIM_DIV_Q16 && b.val.i == 0) return -8; s->stack[s->sp++] = eval_prim(p, a, b); } else if (instr.op == OP_HALT) { s->halted = true; } s->pc = npc; return 0; } /* ── Run (fuel-bounded) ────────────────────────────────────── */ int run(State *s, const Instr *prog, int prog_len, int fuel) { for (int i = 0; i < fuel; i++) { if (s->halted) return 0; int err = step(s, prog, prog_len); if (err) return err; } return 0; }