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

201 lines
12 KiB
C

#ifndef UNDAR_OPCODES_H
#define UNDAR_OPCODES_H
#include "common.h"
typedef enum {
OP_EXIT, /* exit : terminate execution with code [src1] */
OP_CALL, /* call : creates a new frame */
OP_RETURN, /* return : returns from a frame to the parent frame */
OP_SYSCALL, /* syscall : src1 src2 src3 src4 more? does a system call based on args */
OP_LOAD_IMM, /* load_immediate : locals[dest] = constant */
OP_LOAD_IND_8, /* load_indirect_8 : locals[dest] = memory[locals[src1]] as u8 */
OP_LOAD_IND_16, /* load_indirect_16 : locals[dest] = memory[locals[src1]] as u8 */
OP_LOAD_IND_32, /* load_indirect_32 : locals[dest] = memory[locals[src1]] as u32 */
OP_LOAD_ABS_8, /* load_absolute_8 : locals[dest] = memory[src1 as u32] */
OP_LOAD_ABS_16, /* load_absolute_16 : locals[dest] = memory[src1 as u32] */
OP_LOAD_ABS_32, /* load_absolute_32 : locals[dest] = memory[src1 as u32] */
OP_LOAD_OFF_8, /* load_offset_8 : locals[dest] = memory[locals[src1] + offset] as u8 */
OP_LOAD_OFF_16, /* load_offset_16 : locals[dest] = memory[locals[src1] + offset] as u16 */
OP_LOAD_OFF_32, /* load_offset_32 : locals[dest] = memory[locals[src1] + offset] as u32 */
OP_STORE_ABS_8, /* store_absolute_8 : memory[dest] = src1 && 0xFF */
OP_STORE_ABS_16, /* store_absolute_16 : memory[dest] = src1 && 0xFFFF */
OP_STORE_ABS_32, /* store_absolute_32 : memory[dest] = src1 */
OP_STORE_IND_8, /* store_indirect_8 : memory[dest] = locals[src1] && 0xFF */
OP_STORE_IND_16, /* store_indirect_16 : memory[dest] = locals[src1] && 0xFFFF*/
OP_STORE_IND_32, /* store_indirect_32 : memory[dest] = locals[src1] */
OP_STORE_OFF_8, /* store_offset_8 : memory[locals[dest] + offset] = locals[src1] && 0xFF */
OP_STORE_OFF_16, /* store_offset_16 : memory[locals[dest] + offset] = locals[src1] && 0xFFFF */
OP_STORE_OFF_32, /* store_offset_32 : memory[locals[dest] + offset] = locals[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_REG_MOV, /* register_move : locals[dest] = locals[src1] */
OP_ADD_INT, /* add_int : locals[dest] = locals[src1] + locals[src2] */
OP_SUB_INT, /* sub_int : locals[dest] = locals[src1] _ locals[src2] */
OP_MUL_INT, /* mul_int : locals[dest] = locals[src1] * locals[src2] */
OP_DIV_INT, /* div_int : locals[dest] = locals[src1] / locals[src2] */
OP_ABS_INT, /* abs_int : locals[dest] = | locals[src1] | */
OP_NEG_INT, /* neg_int : locals[dest] = -locals[src1] */
OP_ADD_NAT, /* add_nat : locals[dest] = locals[src1] + locals[src2] */
OP_SUB_NAT, /* sub_nat : locals[dest] = locals[src1] _ locals[src2] */
OP_MUL_NAT, /* mul_nat : locals[dest] = locals[src1] * locals[src2] */
OP_DIV_NAT, /* div_nat : locals[dest] = locals[src1] / locals[src2] */
OP_ABS_NAT, /* abs_nat : locals[dest] = | locals[src1] | */
OP_NEG_NAT, /* neg_nat : locals[dest] = -locals[src1] */
OP_ADD_REAL, /* add_real : locals[dest] = locals[src1] + locals[src2] */
OP_SUB_REAL, /* sub_real : locals[dest] = locals[src1] _ locals[src2] */
OP_MUL_REAL, /* mul_real : locals[dest] = locals[src1] * locals[src2] */
OP_DIV_REAL, /* div_real : locals[dest] = locals[src1] / locals[src2] */
OP_ABS_REAL, /* abs_real : locals[dest] = | locals[src1] | */
OP_NEG_REAL, /* neg_real : locals[dest] = _locals[src1] */
OP_INT_TO_REAL, /* int_to_real : locals[dest] = locals[src1] as real */
OP_INT_TO_NAT, /* int_to_nat : locals[dest] = locals[src1] as nat */
OP_NAT_TO_REAL, /* nat_to_real : locals[dest] = locals[src1] as real */
OP_NAT_TO_INT, /* nat_to_int : locals[dest] = locals[src1] as int */
OP_REAL_TO_INT, /* real_to_int : locals[dest] = locals[src1] as int */
OP_REAL_TO_NAT, /* real_to_nat : locals[dest] = locals[src1] as nat */
OP_BIT_SHIFT_LEFT, /* bit_shift_left : locals[dest] = locals[src1] << locals[src2] */
OP_BIT_SHIFT_RIGHT,/* bit_shift_right : locals[dest] = locals[src1] >> locals[src2] */
OP_BIT_SHIFT_R_EXT,/* bit_shift_r_ext : locals[dest] as i32 = locals[src1] >> locals[src2] */
OP_BAND, /* bit_and : locals[dest] = locals[src1] & locals[src2] */
OP_BOR, /* bit_or : locals[dest] = locals[src1] | locals[src2] */
OP_BXOR, /* bit_xor : locals[dest] = locals[src1] ^ locals[src2] */
OP_JMP, /* jump : jump to &dest unconditionally */
OP_JMPF, /* jump_if_flag : jump to &dest if flag != 0 */
OP_JEQ_INT, /* jump_eq_int : jump to &dest if locals[src1] as int == locals[src2] as int */
OP_JNEQ_INT, /* jump_neq_int : jump to &dest if locals[src1] as int != locals[src2] as int */
OP_JGT_INT, /* jump_gt_int : jump to &dest if locals[src1] as int > locals[src2] as int */
OP_JLT_INT, /* jump_lt_int : jump to &dest if locals[src1] as int < locals[src2] as int */
OP_JLE_INT, /* jump_le_int : jump to &dest if locals[src1] as int <= locals[src2] as int */
OP_JGE_INT, /* jump_ge_int : jump to &dest if locals[src1] as int >= locals[src2] as int */
OP_JEQ_NAT, /* jump_eq_nat : jump to &dest if locals[src1] as nat == locals[src2] as nat */
OP_JNEQ_NAT, /* jump_neq_nat : jump to &dest if locals[src1] as nat != locals[src2] as nat */
OP_JGT_NAT, /* jump_gt_nat : jump to &dest if locals[src1] as nat > locals[src2] as nat */
OP_JLT_NAT, /* jump_lt_nat : jump to &dest if locals[src1] as nat < locals[src2] as nat */
OP_JLE_NAT, /* jump_le_nat : jump to &dest if locals[src1] as nat <= locals[src2] as nat */
OP_JGE_NAT, /* jump_ge_nat : jump to &dest if locals[src1] as nat >= locals[src2] as nat */
OP_JEQ_REAL, /* jump_eq_real : jump to &dest if locals[src1] as real == locals[src2] as real */
OP_JNEQ_REAL, /* jump_neq_real : jump to &dest if locals[src1] as real != locals[src2] as real */
OP_JGE_REAL, /* jump_ge_real : jump to &dest if locals[src1] as real >= locals[src2] as real */
OP_JGT_REAL, /* jump_gt_real : jump to &dest if locals[src1] as real > locals[src2] as real */
OP_JLT_REAL, /* jump_lt_real : jump to &dest if locals[src1] as real < locals[src2] as real */
OP_JLE_REAL, /* jump_le_real : jump to &dest if locals[src1] as real <= locals[src2] as real */
OP_STRLEN, /* string_length : locals[dest] = length of str at src1 ptr */
OP_STREQ, /* string_eq : locals[dest] = src1 ptr string == src2 ptr string */
OP_STRCAT, /* string_concat : locals[dest] = ptr of src1 ptr string + src2 ptr string */
OP_STR_GET_CHAR, /* string_get_char : locals[dest] = ptr of src1 ptr str, src2 index of str */
OP_STR_FIND_CHAR, /* string_find_char : locals[dest] = ptr of src1 ptr string, src2 nat8 char */
OP_STR_SLICE, /* string_slice : locals[dest] = ptr of src1 ptr str, src2 start index, src3 end index */
OP_INT_TO_STRING, /* int_to_string : locals[dest] = src1 as str */
OP_NAT_TO_STRING, /* nat_to_string : locals[dest] = src1 as str */
OP_REAL_TO_STRING, /* real_to_string : locals[dest] = src1 as str */
OP_STRING_TO_INT, /* string_to_int : locals[dest] = src1 as int */
OP_STRING_TO_NAT, /* string_to_nat : locals[dest] = src1 as nat */
OP_STRING_TO_REAL, /* string_to_real : locals[dest] = src1 as real */
OP_MAX_OPCODE /* not really an opcode but used to check max length of ops */
} Opcode;
#define MAX_LOCALS 32
typedef struct frame_s {
u32 locals[MAX_LOCALS]; /* $0-$31 */
u32 start; /* start of memory block */
u32 end; /* end of memory block */
u32 return_reg; /* register to store return value in parent */
u32 heap_mask; /* bitfield: 1 bit per register (R0=bit0, R1=bit1, etc) */
} Frame;
typedef enum {
SYSCALL_EXIT = 0,
SYSCALL_DEVICE_OPEN,
SYSCALL_DEVICE_READ,
SYSCALL_DEVICE_WRITE,
SYSCALL_DEVICE_CLOSE,
SYSCALL_DEVICE_IOCTL,
SYSCALL_DEVICE_REFRESH
} SyscallID;
typedef struct device_ops_s {
i32 (*open)(void *device_data, u32 mode, u32 handle, u8 *buffer, u32 size);
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 */
i32 (*refresh)(void *device_data, u8 *buffer);
} DeviceOps;
typedef struct device_s {
const char *type; /* e.g., "screen", "mouse", "gpio" */
const char *path; /* "/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 */
u32 size; /* 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 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 */
Device devices[DEVICES_SIZE]; /* device definitions */
u8 code[CODE_SIZE]; /* code block */
u8 memory[MEMORY_SIZE]; /* memory block */
} VM;
/**
* Creates a new vm based on the arch.
*/
bool init_vm(VM *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