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