#ifndef ZRE_OPCODES_H #define ZRE_OPCODES_H #include "common.h" typedef enum { OP_HALT, /* halt : terminate execution */ OP_JMP, /* jump : jump to address dest unconditionally */ OP_CALL, /* call : creates a new frame */ OP_RETURN, /* retn : returns from a frame to the parent frame */ OP_LOAD, /* load : dest = &[next memory location] */ OP_LOAD_IMM, /* load : dest = &[next memory location] */ OP_STORE, /* stor : next memory location = src1 as float */ OP_PUSH, /* push : push str ref from register onto the stack and copy str */ OP_POP, /* pop : pop int from stack onto the register */ OP_REG_MOV, /* rmov : dest = src1 */ OP_SYSCALL, /* sysc : */ OP_ADD_INT, /* addi : dest = src1 + src2 */ OP_SUB_INT, /* subi : dest = src1 - src2 */ OP_MUL_INT, /* muli : dest = src1 * src2 */ OP_DIV_INT, /* divi : dest = src1 / src2 */ OP_ADD_UINT, /* addu : dest = src1 + src2 */ OP_SUB_UINT, /* subu : dest = src1 - src2 */ OP_MUL_UINT, /* mulu : dest = src1 * src2 */ OP_DIV_UINT, /* divu : dest = src1 / src2 */ OP_ADD_REAL, /* addr : dest = src1 + src2 */ OP_SUB_REAL, /* subr : dest = src1 - src2 */ OP_MUL_REAL, /* mulr : dest = src1 * src2 */ OP_DIV_REAL, /* divr : dest = src1 / src2 */ OP_INT_TO_REAL, /* itor : dest = src1 as real */ OP_UINT_TO_REAL, /* utor : dest = src1 as real */ OP_REAL_TO_INT, /* rtoi : dest = src1 as int */ OP_REAL_TO_UINT, /* rtou : dest = src1 as uint */ OP_JEQ_INT, /* jeqi : jump to address dest if src1 as int == src2 as int */ OP_JGT_INT, /* jgti : jump to address dest if src1 as int > src2 as int*/ OP_JLT_INT, /* jlti : jump to address dest if src1 as int < src2 as int */ OP_JLE_INT, /* jlei : jump to address dest if src1 as int <= src2 as int */ OP_JGE_INT, /* jgei : jump to address dest if src1 as int >= src2 as int*/ OP_JEQ_UINT, /* jequ : jump to address dest if src1 as int == src2 as uint */ OP_JGT_UINT, /* jgtu : jump to address dest if src1 as int > src2 as uint*/ OP_JLT_UINT, /* jltu : jump to address dest if src1 as int < src2 as uint */ OP_JLE_UINT, /* jleu : jump to address dest if src1 as int <= src2 as uint */ OP_JGE_UINT, /* jgeu : jump to address dest if src1 as int >= src2 as uint*/ OP_JEQ_REAL, /* jeqr : jump to address dest if src1 as real == src2 as real */ OP_JGE_REAL, /* jgtr : jump to address dest if src1 as real >= src2 as real */ OP_JGT_REAL, /* jltr : jump to address dest if src1 as real > src2 as real */ OP_JLT_REAL, /* jler : jump to address dest if src1 as real < src2 as real */ OP_JLE_REAL, /* jger : jump to address dest if src1 as real <= src2 as real */ OP_STRLEN, /* strl : dest = length of str at src1 ptr */ OP_INT_TO_STRING, /* itos : dest = src1 as str */ OP_UINT_TO_STRING, /* utos : dest = src1 as str */ OP_REAL_TO_STRING, /* rtos : dest = src1 as str */ OP_STRING_TO_INT, /* stoi : dest = src1 as int */ OP_STRING_TO_UINT, /* stou : dest = src1 as uint */ OP_STRING_TO_REAL /* stor : dest = src1 as real */ } Opcode; #define MAX_REGS 32 typedef struct frame_s { u32 registers[MAX_REGS]; /* R0-R31 */ u32 rp; /* register pointer (last unused) */ u32 start; /* start and end of global allocated block */ u32 end; } Frame; typedef enum { SYSCALL_EXIT = 0, SYSCALL_DEVICE_OPEN, SYSCALL_DEVICE_READ, SYSCALL_DEVICE_WRITE, SYSCALL_DEVICE_CLOSE, SYSCALL_DEVICE_IOCTL } SyscallID; typedef struct device_ops_s { i32 (*open)(void *device_data, u32 mode); i32 (*read)(void *device_data, u8 *buffer, u32 size); i32 (*write)(void *device_data, const u8 *buffer, u32 size); i32 (*close)(void *device_data); i32 (*ioctl)(void *device_data, u32 cmd, void *args); /* optional control */ } DeviceOps; #define DEVICE_TYPE_MAX_LENGTH 24 /* 23 chars + null terminator */ #define DEVICE_PATH_MAX_LENGTH 64 /* 63 chars + null terminator */ typedef struct device_s { char type[DEVICE_TYPE_MAX_LENGTH]; /* e.g., "screen", "mouse", "gpio" */ char path[DEVICE_PATH_MAX_LENGTH]; /* "/dev/screen", "/dev/input/mouse/0", etc. */ void *data; /* device-specific data */ DeviceOps *ops; /* operations vtable */ u32 flags; /* permissions, status, etc. */ } Device; #define MEMORY_SIZE 1024 /*(640 * 480 + 65536)*/ #define CODE_SIZE 128 /*8192*/ #define FRAMES_SIZE 128 #define STACK_SIZE 256 #define DEVICES_SIZE 8 typedef struct vm_s { u32 pc; /* program counter */ u32 cp; /* code pointer (last allocated opcode) */ u32 fp; /* frame pointer (current frame) */ u32 sp; /* stack pointer (top of stack) */ u32 rp; /* return stack pointer (top of stack) */ u32 mp; /* memory pointer (last allocated value) */ u32 dc; /* device count */ u32 acc; /* accumulator (temporary results like SYSCALL status) */ Frame frames[FRAMES_SIZE]; /* function call frames */ u32 stack[STACK_SIZE]; /* main stack */ u32 return_stack[STACK_SIZE]; /* return stack (for call recursion) */ Device devices[DEVICES_SIZE]; /* device definitions */ u8 code[CODE_SIZE]; /* code block */ u8 memory[MEMORY_SIZE]; /* memory block */ } VM; #define AS_INT(v) ((i32)(v)) #define AS_UINT(v) ((u32)(v)) #define AS_FIXED(v) ((float)(i32)(v) / 65536.0f) #define TO_FIXED(f) ((u32)((i32)( \ ((f) >= 0.0f) ? ((f) * 65536.0f + 0.5f) : ((f) * 65536.0f - 0.5f) \ ))) #define read_u8(vm, location, addr) ((vm)->location[addr]) #define read_u16(vm, location, addr) \ (((uint16_t)(vm)->location[(addr)] << 8) | \ ((uint16_t)(vm)->location[(addr) + 1])) #define read_u32(vm, location, addr) \ (((u32)(vm)->location[(addr)] << 24) | \ ((u32)(vm)->location[(addr) + 1] << 16) | \ ((u32)(vm)->location[(addr) + 2] << 8) | ((u32)(vm)->location[(addr) + 3])) #define write_u8(vm, location, addr, value) \ do { \ if ((addr) < sizeof((vm)->location)) { \ (vm)->location[(addr)] = (value); \ } \ } while (0) #define write_u16(vm, location, addr, value) \ do { \ if ((addr) + 1 < sizeof((vm)->location)) { \ (vm)->location[(addr)] = ((value) >> 8) & 0xFF; \ (vm)->location[(addr) + 1] = (value) & 0xFF; \ } \ } while (0) #define write_u32(vm, location, addr, value) \ do { \ if ((addr) + 3 < sizeof((vm)->location)) { \ (vm)->location[(addr)] = ((value) >> 24) & 0xFF; \ (vm)->location[(addr) + 1] = ((value) >> 16) & 0xFF; \ (vm)->location[(addr) + 2] = ((value) >> 8) & 0xFF; \ (vm)->location[(addr) + 3] = (value) & 0xFF; \ } \ } while (0) #endif