make ADD work with uint8
This commit is contained in:
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"VMOP"
|
||||
]
|
||||
}
|
||||
136
main.c
Normal file
136
main.c
Normal file
@@ -0,0 +1,136 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define REGISTER_SIZE (1 << 6) // 64 register , overkill IK
|
||||
|
||||
/*
|
||||
the types are defined using the X macro patter in this order
|
||||
(enum name, actual c type, the value used in the union)
|
||||
*/
|
||||
#define VM_TYPES \
|
||||
X(UINT8, uint8_t, _uint8_val) \
|
||||
X(UINT16, uint16_t, _uint16_val) \
|
||||
X(UINT32, uint32_t, _uint32_val) \
|
||||
X(UINT64, uint64_t, _uint64_val) \
|
||||
X(PTR, uintptr_t, _uintptr_val)
|
||||
|
||||
#define VM_OPCODES \
|
||||
X(OP_ADD, vm_add) \
|
||||
X(OP_SET_REG, vm_set_reg) \
|
||||
X(OP_PRINT, vm_print) \
|
||||
X(OP_END, vm_end)
|
||||
|
||||
// given context pointer perform operations on the register
|
||||
#define GET_REGISTER(CTX_P, IDX) (CTX_P)->registers[(IDX)]
|
||||
|
||||
#define SET_REGISTER(CTX_P, IDX, TYPE, VALUE) ((CTX_P)->registers[(IDX)].type = (TYPE), vm_set_value((CTX_P), (IDX), (TYPE), (VALUE)))
|
||||
|
||||
// clang-format off
|
||||
typedef enum {
|
||||
#define X(name, ctype, field) name,
|
||||
VM_TYPES
|
||||
#undef X
|
||||
} VMTypes;
|
||||
|
||||
typedef enum {
|
||||
#define X(op_name, op_func) op_name,
|
||||
VM_OPCODES
|
||||
#undef X
|
||||
} VMOPCodes;
|
||||
|
||||
typedef struct {
|
||||
VMTypes type;
|
||||
|
||||
union {
|
||||
#define X(name, ctype, field) ctype field;
|
||||
VM_TYPES
|
||||
#undef X
|
||||
} value;
|
||||
} VMType;
|
||||
|
||||
typedef struct {
|
||||
VMType registers[REGISTER_SIZE];
|
||||
} VMCtx;
|
||||
|
||||
typedef void (*vm_op_func_t)(VMCtx *, uint8_t *, size_t *);
|
||||
// clang-format on
|
||||
|
||||
void vm_set_value(VMCtx *ctx, size_t idx, VMTypes type, uintptr_t value) {
|
||||
// clang-format off
|
||||
switch(type) {
|
||||
#define X(name, ctype, field) \
|
||||
case name: { \
|
||||
ctx->registers[idx].value.field = value; \
|
||||
break; \
|
||||
} \
|
||||
|
||||
VM_TYPES
|
||||
#undef X
|
||||
}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void vm_add(VMCtx *ctx, uint8_t *program, size_t *pc) {
|
||||
(*pc)++;
|
||||
size_t op1_idx = program[(*pc)++];
|
||||
size_t op2_idx = program[(*pc)++];
|
||||
size_t dest_idx = program[(*pc)++];
|
||||
|
||||
vm_set_value(ctx, dest_idx, UINT8, GET_REGISTER(ctx, op1_idx).value._uint8_val + GET_REGISTER(ctx, op2_idx).value._uint8_val);
|
||||
}
|
||||
|
||||
void vm_set_reg(VMCtx *ctx, uint8_t *program, size_t *pc) {
|
||||
(*pc)++;
|
||||
size_t idx = program[(*pc)++];
|
||||
VMTypes type = (VMTypes)program[(*pc)++];
|
||||
vm_set_value(ctx, idx, type, program[(*pc)++]);
|
||||
}
|
||||
|
||||
void vm_print(VMCtx *ctx, uint8_t *program, size_t *pc) {
|
||||
(*pc)++;
|
||||
printf("vm_print %d\n", GET_REGISTER(ctx, program[(*pc)++]).value._uint8_val);
|
||||
}
|
||||
void vm_end(VMCtx *ctx, uint8_t *program, size_t *pc) {
|
||||
(*pc)++;
|
||||
}
|
||||
// clang-format off
|
||||
vm_op_func_t vm_funcs[] = {
|
||||
#define X(op_name, op_func) [op_name] = op_func,
|
||||
VM_OPCODES
|
||||
#undef X
|
||||
};
|
||||
|
||||
// clang-format on
|
||||
|
||||
void vm_eval(VMCtx *ctx, uint8_t *program) {
|
||||
size_t pc = 0;
|
||||
|
||||
while (program[pc] != OP_END) {
|
||||
// pc++;
|
||||
vm_funcs[program[pc]](ctx, program, &pc);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
VMCtx ctx = {0};
|
||||
|
||||
// clang-format off
|
||||
uint8_t program[] = {
|
||||
OP_SET_REG, 0, UINT8, 35,
|
||||
OP_SET_REG, 1, UINT8, 34,
|
||||
OP_ADD, 0, 1, 2,
|
||||
OP_PRINT, 2,
|
||||
OP_END
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// SET_REGISTER(&ctx, 0, UINT8, 12);
|
||||
// SET_REGISTER(&ctx, 1, UINT8, 15);
|
||||
|
||||
// printf("Add = %d\n", ctx.registers[0].value._uint8_val + ctx.registers[1].value._uint8_val);
|
||||
|
||||
vm_eval(&ctx, program);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user