1
0
Fork 0
undar-lang-old/src/vm/opcodes.h

184 lines
11 KiB
C

#ifndef ZRE_OPCODES_H
#define ZRE_OPCODES_H
#include "common.h"
typedef enum {
OP_HALT, /* halt : terminate execution with code [src1] */
OP_JMP, /* jump : jump to address dest unconditionally */
OP_JMPF, /* jump-if-flag : jump to address dest if flag is ne 0 */
OP_CALL, /* call : creates a new frame */
OP_RETURN, /* return : returns from a frame to the parent frame */
OP_LOAD_IMM, /* load-immediate : dest = constant */
OP_GET_8, /* get-8 : dest = memory[registers[src1]] as u8 */
OP_GET_16, /* get-16 : dest = memory[registers[src1]] as u8 */
OP_GET_32, /* get : dest = memory[registers[src1]] as u32 */
OP_LOAD_8, /* load-8 : dest = memory[src1 as u32] */
OP_LOAD_16, /* load-16 : dest = memory[src1 as u32] */
OP_LOAD_32, /* load : dest = memory[src1 as u32] */
OP_STORE_8, /* store-8 : memory[dest] = src1 << 8 */
OP_STORE_16, /* store-16 : memory[dest] = src1 << 16 */
OP_STORE_32, /* store : memory[dest] = src1 */
OP_PUT_8, /* put-8 : memory[dest] = registers[src1] << 8 */
OP_PUT_16, /* put-16 : memory[dest] = registers[src1] << 16*/
OP_PUT_32, /* put : memory[dest] = registers[src1] */
OP_MALLOC, /* malloc : dest = fat ptr to memory of ((src1 as size) + 4) */
OP_MEMSET_8, /* memset-8 : dest <-> dest+count = src1 as u8 */
OP_MEMSET_16, /* memset-16 : dest <-> dest+count = src1 as u8 */
OP_MEMSET_32, /* memset-32 : dest <-> dest+count = src1 as u32 */
OP_PUSH, /* push : push const of ref */
OP_POP, /* pop : pop cosnt or ref */
OP_REG_MOV, /* register-move : dest = src1 */
OP_SYSCALL, /* syscall : src1 src2 src3 src4 more? does a system call based on args */
OP_SLL, /* bit-shift-left : dest = src1 << src2 */
OP_SRL, /* bit-shift-right : dest = src1 >> src2 */
OP_SRE, /* bit-shift-re : dest as i32 = src1 >> src2 */
OP_BAND, /* bit-and : dest = src1 & src2 */
OP_BOR, /* bit-or : dest = src1 | src2 */
OP_BXOR, /* bit-xor : dest = src1 ^ src2 */
OP_ADD_INT, /* add-int : dest = src1 + src2 */
OP_SUB_INT, /* sub-int : dest = src1 - src2 */
OP_MUL_INT, /* mul-int : dest = src1 * src2 */
OP_DIV_INT, /* div-int : dest = src1 / src2 */
OP_ADD_UINT, /* add-nat : dest = src1 + src2 */
OP_SUB_UINT, /* sub-nat : dest = src1 - src2 */
OP_MUL_UINT, /* mul-nat : dest = src1 * src2 */
OP_DIV_UINT, /* div-nat : dest = src1 / src2 */
OP_ADD_REAL, /* add-real : dest = src1 + src2 */
OP_SUB_REAL, /* sub-real : dest = src1 - src2 */
OP_MUL_REAL, /* mul-real : dest = src1 * src2 */
OP_DIV_REAL, /* div-real : dest = src1 / src2 */
OP_INT_TO_REAL, /* int-to-real : dest = src1 as real */
OP_UINT_TO_REAL, /* nat-to-real : dest = src1 as real */
OP_REAL_TO_INT, /* real-to-int : dest = src1 as int */
OP_REAL_TO_UINT, /* real-to-nat : dest = src1 as uint */
OP_JEQ_INT, /* jump-eq-int : jump to address dest if src1 as int == src2 as int */
OP_JNEQ_INT, /* jump-neq-int : jump to address dest if src1 as int != src2 as int */
OP_JGT_INT, /* jump-gt-int : jump to address dest if src1 as int > src2 as int */
OP_JLT_INT, /* jump-lt-int : jump to address dest if src1 as int < src2 as int */
OP_JLE_INT, /* jump-le-int : jump to address dest if src1 as int <= src2 as int */
OP_JGE_INT, /* jump-ge-int : jump to address dest if src1 as int >= src2 as int */
OP_JEQ_UINT, /* jump-eq-nat : jump to address dest if src1 as uint == src2 as uint */
OP_JNEQ_UINT, /* jump-neq-nat : jump to address dest if src1 as uint != src2 as uint */
OP_JGT_UINT, /* jump-gt-nat : jump to address dest if src1 as uint > src2 as uint */
OP_JLT_UINT, /* jump-lt-nat : jump to address dest if src1 as uint < src2 as uint */
OP_JLE_UINT, /* jump-le-nat : jump to address dest if src1 as uint <= src2 as uint */
OP_JGE_UINT, /* jump-ge-nat : jump to address dest if src1 as uint >= src2 as uint */
OP_JEQ_REAL, /* jump-eq-real : jump to address dest if src1 as real == src2 as real */
OP_JNEQ_REAL, /* jump-neq-real : jump to address dest if src1 as real != src2 as real */
OP_JGE_REAL, /* jump-ge-real : jump to address dest if src1 as real >= src2 as real */
OP_JGT_REAL, /* jump-gt-real : jump to address dest if src1 as real > src2 as real */
OP_JLT_REAL, /* jump-lt-real : jump to address dest if src1 as real < src2 as real */
OP_JLE_REAL, /* jump-le-real : jump to address dest if src1 as real <= src2 as real */
OP_STRLEN, /* string-length : dest = length of str at src1 ptr */
OP_STREQ, /* string-eq : dest = src1 ptr string == src2 ptr string */
OP_STRCAT, /* string-concat : dest = ptr of src1 ptr string + src2 ptr string */
OP_STR_GET_CHAR, /* string-get-char : dest = ptr of src1 ptr str, src2 index of str */
OP_STR_FIND_CHAR, /* string-find-char : dest = ptr of src1 ptr string, src2 uint8 char */
OP_STR_SLICE, /* string-slice : dest = ptr of src1 ptr str, src2 start index, src3 end index */
OP_INT_TO_STRING, /* int-to-string : dest = src1 as str */
OP_UINT_TO_STRING, /* nat-to-string : dest = src1 as str */
OP_REAL_TO_STRING, /* real-to-string : dest = src1 as str */
OP_STRING_TO_INT, /* string-to-int : dest = src1 as int */
OP_STRING_TO_UINT, /* string-to-nat : dest = src1 as uint */
OP_STRING_TO_REAL /* string-to-real : 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,
const u8 *buffer); /* optional control */
} DeviceOps;
#define DEVICE_TYPE_MAX_LENGTH 16 /* 15 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. */
u32 handle; /* id for fast access in VM */
} Device;
#define MEMORY_SIZE (640 * 480 + 65536)
#define CODE_SIZE 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 */
i32 flag; /* flag (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 read_u8(vm, location, addr) ((vm)->location[addr])
#define read_u16(vm, location, addr) \
(((u16)(vm)->location[(addr) + 1] << 8) | ((u16)(vm)->location[(addr)]))
#define read_u32(vm, location, addr) \
(((u32)(vm)->location[(addr) + 3] << 24) | \
((u32)(vm)->location[(addr) + 2] << 16) | \
((u32)(vm)->location[(addr) + 1] << 8) | ((u32)(vm)->location[(addr)]))
#define write_u8(vm, location, addr, value) \
do { \
if ((addr) < sizeof((vm)->location)) { \
(vm)->location[(addr)] = (value) & 0xFF; \
} \
} while (0)
#define write_u16(vm, location, addr, value) \
do { \
if ((addr) + 1 < sizeof((vm)->location)) { \
(vm)->location[(addr)] = (value) & 0xFF; \
(vm)->location[(addr) + 1] = ((value) >> 8) & 0xFF; \
} \
} while (0)
#define write_u32(vm, location, addr, value) \
do { \
if ((addr) + 3 < sizeof((vm)->location)) { \
(vm)->location[(addr)] = (value) & 0xFF; \
(vm)->location[(addr) + 1] = ((value) >> 8) & 0xFF; \
(vm)->location[(addr) + 2] = ((value) >> 16) & 0xFF; \
(vm)->location[(addr) + 3] = ((value) >> 24) & 0xFF; \
} \
} while (0)
#endif