Files

15 lines
5.0 KiB
C

#include "vm.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
void vm_init(VM *vm, uint32_t *code, uint32_t code_len, ExtSlot *ext_ops, uint32_t ext_ops_count) { memset(vm, 0, sizeof(VM)); vm->code = code; vm->code_len = code_len; vm->ext_ops = ext_ops; vm->ext_ops_count = ext_ops_count; vm->running = true; vm->trace_enabled = false; vm->current_mode = MODE_USER; }
static MemoryRegion *find_region(VM *vm, HandleId id) { for (uint32_t i = 0; i < vm->region_count; i++) { if (vm->regions[i].id == id) return &vm->regions[i]; } return NULL; }
static void trace_instr(VM *vm, GlyphInstr *ins, uint32_t word) { if (!vm->trace_enabled) return; uint8_t op_a, op_b; glyph_decode_ops(ins->opcode_local, &op_a, &op_b); printf("[%04u] 0x%08X | %s F%02u.%u mode=%s opc=%s A=%u B=%u\n", vm->pc - 1, word, glyph_lineage_str(ins->family_id), ins->family_id, ins->sub_id, glyph_mode_str(ins->mode), glyph_opclass_str(ins->opclass), op_a, op_b); }
static int exec_mem(VM *vm, GlyphInstr *ins) { uint8_t op_a, op_b; glyph_decode_ops(ins->opcode_local, &op_a, &op_b); switch (ins->family_id) { case 0: case 1: { MemoryRegion *r = find_region(vm, (HandleId)op_a); if (!r) { if (vm->region_count >= MAX_REGIONS) return -1; r = &vm->regions[vm->region_count++]; r->id = (HandleId)op_a; r->size = 256; r->bytes = calloc(r->size, 1); r->traits = 0; r->resonance = 1.0f; r->stability = 1.0f; r->lineage_id = 0; r->sealed = false; r->mutation_count = 0; } if (r->sealed) return -1; if (op_b < r->size) r->bytes[op_b] = (uint8_t)(vm->regs[op_b] & 0xFF); r->mutation_count++; r->stability = substrate_stability_from_mutations(r->mutation_count); break; } case 2: { MemoryRegion *r = find_region(vm, (HandleId)op_a); if (!r) { vm->regs[op_a] = 0; } else { if (op_b < r->size) vm->regs[op_a] = (int32_t)r->bytes[op_b]; r->resonance = substrate_resonance(vm->tick > 0 ? (uint32_t)(vm->tick % 10) : 0); } break; } case 4: { if (vm->region_count >= MAX_REGIONS) return -1; MemoryRegion *r = &vm->regions[vm->region_count++]; uint32_t size = (uint32_t)vm->regs[op_b]; if (size == 0) size = 256; r->id = (HandleId)op_a; r->size = size; r->bytes = calloc(size, 1); r->traits = 0; r->resonance = 1.0f; r->stability = 1.0f; r->lineage_id = 0; r->sealed = false; r->mutation_count = 0; break; } case 5: switch (ins->sub_id) { case 2: { MemoryRegion *r = find_region(vm, (HandleId)op_a); if (r && !r->sealed) { for (uint32_t i = 0; i < r->size; i++) r->bytes[i] = (uint8_t)(i & 0xFF); r->mutation_count += r->size; r->stability = substrate_stability_from_mutations(r->mutation_count); } break; } case 3: { MemoryRegion *r = find_region(vm, (HandleId)op_a); if (r && !r->sealed) { for (uint32_t i = 0; i < r->size; i++) r->bytes[i] = (i % 2 == 0) ? (uint8_t)(200 + (i % 50)) : (uint8_t)(5 + (i % 10)); r->mutation_count += r->size; r->stability = substrate_stability_from_mutations(r->mutation_count); } break; } case 4: { MemoryRegion *r = find_region(vm, (HandleId)op_a); if (r && !r->sealed) { memset(r->bytes, (uint8_t)(vm->regs[op_b] & 0xFF), r->size); r->mutation_count += r->size; r->stability = substrate_stability_from_mutations(r->mutation_count); } break; } } break; case 7: { MemoryRegion *r = find_region(vm, (HandleId)op_a); if (r) { if (ins->sub_id == 1 && ins->mode >= MODE_KERNEL) r->sealed = true; vm->cmp_flag = (r->bytes != NULL) ? 1 : 0; } break; } default: break; } return 0; }
static int exec_cmp(VM *vm, GlyphInstr *ins) { uint8_t op_a, op_b; glyph_decode_ops(ins->opcode_local, &op_a, &op_b); int32_t a = vm->regs[op_a]; int32_t b = vm->regs[op_b]; switch (ins->family_id) { case 8: vm->regs[op_a] = a + b; break; case 20: vm->running = false; return -1; } return 0; }
static int exec_ctl(VM *vm, GlyphInstr *ins) { uint8_t op_a, op_b; glyph_decode_ops(ins->opcode_local, &op_a, &op_b); switch (ins->family_id) { case 20: vm->running = false; return -1; case 21: if (ins->sub_id == 2) { if (vm->pc < vm->code_len) { vm->regs[op_a] = (int32_t)vm->code[vm->pc++]; vm->tick++; } } break; } return 0; }
int vm_step(VM *vm) { if (vm->pc >= vm->code_len) { vm->running = false; return -1; } uint32_t word = vm->code[vm->pc++]; GlyphInstr ins = glyph_decode(word); vm->current_mode = ins.mode; vm->tick++; trace_instr(vm, &ins, word); if (ins.family_id <= FAMILY_MEM_END) return exec_mem(vm, &ins); if (ins.family_id <= FAMILY_CMP_END) return exec_cmp(vm, &ins); if (ins.family_id <= FAMILY_CTL_END) return exec_ctl(vm, &ins); return 0; }
void vm_run(VM *vm) { while (vm->running) { if (vm_step(vm) != 0) break; } }
int vm_load_gobj(VM *vm, const char *path) { FILE *f = fopen(path, "rb"); if (!f) return -1; GobjHeader hdr; if (fread(&hdr, sizeof(GobjHeader), 1, f) != 1) { fclose(f); return -1; } if (memcmp(hdr.magic, GOBJ_MAGIC, 8) != 0) { fclose(f); return -1; } uint32_t *code = malloc(hdr.code_len * sizeof(uint32_t)); fread(code, sizeof(uint32_t), hdr.code_len, f); ExtSlot *ext = NULL; if (hdr.ext_len > 0) { ext = calloc(hdr.ext_len, sizeof(ExtSlot)); fread(ext, sizeof(ExtSlot), hdr.ext_len, f); } fclose(f); vm_init(vm, code, hdr.code_len, ext, hdr.ext_len); return 0; }