diff options
author | Aryadev Chavali <aryadev@aryadevchavali.com> | 2023-10-23 00:09:12 +0100 |
---|---|---|
committer | Aryadev Chavali <aryadev@aryadevchavali.com> | 2023-10-23 00:09:12 +0100 |
commit | ae9bc91713f86cfc16e801ca33654a47082ddb2b (patch) | |
tree | 99b3ff0d9e729feeb42689ca181a294199dc69af | |
parent | 45ad8f7296722cc3cec0a6974f9d2519c9f36d4b (diff) | |
download | ovm-ae9bc91713f86cfc16e801ca33654a47082ddb2b.tar.gz ovm-ae9bc91713f86cfc16e801ca33654a47082ddb2b.tar.bz2 ovm-ae9bc91713f86cfc16e801ca33654a47082ddb2b.zip |
Added and implemented OP_PRINT*
Here is where we may have differing interpretations of what the bits
in the data pile may actually mean. This in particular refers to
printing the signed or unsigned versions of the bits given. Also,
interpreting some byte as a character or just a raw number.
-rw-r--r-- | src/inst.c | 26 | ||||
-rw-r--r-- | src/inst.h | 20 | ||||
-rw-r--r-- | src/runtime.c | 77 |
3 files changed, 110 insertions, 13 deletions
@@ -132,6 +132,24 @@ const char *opcode_as_cstr(opcode_t code) case OP_JUMP_REGISTER: return "JUMP_REGISTER"; break; + case OP_PRINT_CHAR: + return "PRINT_CHAR"; + break; + case OP_PRINT_BYTE: + return "PRINT_BYTE"; + break; + case OP_PRINT_INT: + return "PRINT_INT"; + break; + case OP_PRINT_HWORD: + return "PRINT_HWORD"; + break; + case OP_PRINT_LONG: + return "PRINT_LONG"; + break; + case OP_PRINT_WORD: + return "PRINT_WORD"; + break; case OP_HALT: return "HALT"; break; @@ -186,7 +204,7 @@ word convert_bytes_to_word(byte *bytes) void inst_print(inst_t instruction, FILE *fp) { - static_assert(NUMBER_OF_OPCODES == 37, "inst_bytecode_size: Out of date"); + static_assert(NUMBER_OF_OPCODES == 43, "inst_bytecode_size: Out of date"); fprintf(fp, "%s(", opcode_as_cstr(instruction.opcode)); if (OPCODE_IS_TYPE(instruction.opcode, OP_PUSH)) { @@ -215,7 +233,7 @@ void inst_print(inst_t instruction, FILE *fp) size_t inst_bytecode_size(inst_t inst) { - static_assert(NUMBER_OF_OPCODES == 37, "inst_bytecode_size: Out of date"); + static_assert(NUMBER_OF_OPCODES == 43, "inst_bytecode_size: Out of date"); size_t size = 1; // for opcode if (OPCODE_IS_TYPE(inst.opcode, OP_PUSH)) { @@ -240,7 +258,7 @@ size_t inst_bytecode_size(inst_t inst) void inst_write_bytecode(inst_t inst, darr_t *darr) { - static_assert(NUMBER_OF_OPCODES == 37, "inst_write_bytecode: Out of date"); + static_assert(NUMBER_OF_OPCODES == 43, "inst_write_bytecode: Out of date"); // Append opcode darr_append_byte(darr, inst.opcode); // Then append 0 or more operands @@ -313,7 +331,7 @@ data_t read_type_from_darr(darr_t *darr, data_type_t type) inst_t inst_read_bytecode(darr_t *darr) { - static_assert(NUMBER_OF_OPCODES == 37, "inst_read_bytecode: Out of date"); + static_assert(NUMBER_OF_OPCODES == 43, "inst_read_bytecode: Out of date"); if (darr->used >= darr->available) return (inst_t){0}; inst_t inst = {0}; @@ -70,6 +70,14 @@ typedef enum OP_PLUS_HWORD, OP_PLUS_WORD, + // Simple I/O + OP_PRINT_CHAR, + OP_PRINT_BYTE, + OP_PRINT_INT, + OP_PRINT_HWORD, + OP_PRINT_LONG, + OP_PRINT_WORD, + // Program control flow OP_JUMP_ABS, OP_JUMP_STACK, @@ -127,12 +135,11 @@ inst_t *insts_read_bytecode_file(FILE *, size_t *); #define INST_DUP(TYPE, OP) \ ((inst_t){.opcode = OP_DUP_##TYPE, .operand = DWORD(OP)}) -#define INST_NOT(TYPE) ((inst_t){.opcode = OP_NOT_##TYPE}) -#define INST_OR(TYPE) ((inst_t){.opcode = OP_OR_##TYPE}) -#define INST_AND(TYPE) ((inst_t){.opcode = OP_AND_##TYPE}) -#define INST_XOR(TYPE) ((inst_t){.opcode = OP_XOR_##TYPE}) -#define INST_EQ(TYPE) ((inst_t){.opcode = OP_EQ_##TYPE}) - +#define INST_NOT(TYPE) ((inst_t){.opcode = OP_NOT_##TYPE}) +#define INST_OR(TYPE) ((inst_t){.opcode = OP_OR_##TYPE}) +#define INST_AND(TYPE) ((inst_t){.opcode = OP_AND_##TYPE}) +#define INST_XOR(TYPE) ((inst_t){.opcode = OP_XOR_##TYPE}) +#define INST_EQ(TYPE) ((inst_t){.opcode = OP_EQ_##TYPE}) #define INST_PLUS(TYPE) ((inst_t){.opcode = OP_PLUS_##TYPE}) #define INST_JUMP_ABS(OP) \ @@ -140,4 +147,5 @@ inst_t *insts_read_bytecode_file(FILE *, size_t *); #define INST_JUMP_STACK ((inst_t){.opcode = OP_JUMP_STACK}) #define INST_JUMP_REGISTER ((inst_t){.opcode = OP_JUMP_REGISTER}) +#define INST_PRINT(TYPE) ((inst_t){.opcode = OP_PRINT_##TYPE}) #endif diff --git a/src/runtime.c b/src/runtime.c index ac1cf58..f653ac3 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -11,6 +11,7 @@ */ #include <assert.h> +#include <inttypes.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -54,7 +55,7 @@ const char *err_as_cstr(err_t err) err_t vm_execute(vm_t *vm) { - static_assert(NUMBER_OF_OPCODES == 37, "vm_execute: Out of date"); + static_assert(NUMBER_OF_OPCODES == 43, "vm_execute: Out of date"); struct Program *prog = &vm->program; if (prog->ptr >= prog->max) return ERR_END_OF_PROGRAM; @@ -135,12 +136,82 @@ err_t vm_execute(vm_t *vm) return ERR_INVALID_PROGRAM_ADDRESS; prog->ptr = addr; } + else if (instruction.opcode >= OP_PRINT_CHAR && + instruction.opcode <= OP_PRINT_WORD) + { + data_t datum = {0}; + enum + { + TYPE_CHAR, + TYPE_BYTE, + TYPE_INT, + TYPE_HWORD, + TYPE_LONG, + TYPE_WORD + } print_type; + err_t err = ERR_OK; + if (instruction.opcode == OP_PRINT_BYTE || + instruction.opcode == OP_PRINT_CHAR) + { + print_type = instruction.opcode == OP_PRINT_BYTE ? TYPE_BYTE : TYPE_CHAR; + err = vm_pop_byte(vm, &datum); + } + else if (instruction.opcode == OP_PRINT_HWORD || + instruction.opcode == OP_PRINT_INT) + { + print_type = instruction.opcode == OP_PRINT_HWORD ? TYPE_HWORD : TYPE_INT; + err = vm_pop_hword(vm, &datum); + } + else if (instruction.opcode == OP_PRINT_WORD || + instruction.opcode == OP_PRINT_LONG) + { + print_type = instruction.opcode == OP_PRINT_WORD ? TYPE_WORD : TYPE_LONG; + err = vm_pop_word(vm, &datum); + } + + if (err) + return err; + + switch (print_type) + { + case TYPE_CHAR: { + char c = 0; + memcpy(&c, &datum.as_byte, 1); + printf("%c", c); + break; + } + case TYPE_BYTE: + printf("0x%x", datum.as_byte); + break; + case TYPE_INT: { + int32_t i = 0; + memcpy(&i, &datum.as_hword, HWORD_SIZE); + printf("%" PRId32, i); + break; + } + case TYPE_HWORD: + printf("%" PRIu32, datum.as_hword); + break; + case TYPE_LONG: { + int64_t i = 0; + memcpy(&i, &datum.as_word, WORD_SIZE); + printf("%" PRId64, i); + break; + } + case TYPE_WORD: + printf("%" PRIu64, datum.as_word); + break; + } + + prog->ptr++; + } else if (instruction.opcode == OP_HALT) { // Do nothing here. Should be caught by callers of vm_execute - return ERR_OK; } - return ERR_INVALID_OPCODE; + else + return ERR_INVALID_OPCODE; + return ERR_OK; } err_t vm_execute_all(vm_t *vm) |