diff --git a/lib/base.c b/lib/base.c index 8b5a617..486fa91 100644 --- a/lib/base.c +++ b/lib/base.c @@ -16,14 +16,18 @@ hword_t hword_byteswap(const hword_t w) { + // TODO: is there a faster way of doing this? return WORD_NTH_BYTE(w, 3) | (WORD_NTH_BYTE(w, 2) << 8) | - (WORD_NTH_BYTE(w, 1) << 16) | (WORD_NTH_BYTE(w, 0) << 24); + WORD_NTH_BYTE(w, 1) << 16 | WORD_NTH_BYTE(w, 0) << 24; } word_t word_byteswap(const word_t w) { - return ((word_t)(hword_byteswap(WORD_NTH_HWORD(w, 0))) << 32) | - hword_byteswap(WORD_NTH_HWORD(w, 1)); + // TODO: is there a faster way of doing this? + return WORD_NTH_BYTE(w, 7) | WORD_NTH_BYTE(w, 6) << 8 | + WORD_NTH_BYTE(w, 5) << 16 | WORD_NTH_BYTE(w, 4) << 24 | + WORD_NTH_BYTE(w, 3) << 32 | WORD_NTH_BYTE(w, 2) << 40 | + WORD_NTH_BYTE(w, 1) << 48 | WORD_NTH_BYTE(w, 0) << 56; } hword_t convert_bytes_to_hword(const byte_t *bytes) diff --git a/lib/base.h b/lib/base.h index 1c22d98..ae866bc 100644 --- a/lib/base.h +++ b/lib/base.h @@ -97,7 +97,7 @@ typedef enum #define DHWORD(HWORD) ((data_t){.as_hword = (HWORD)}) #define DWORD(WORD) ((data_t){.as_word = (WORD)}) -// Macro to determine little endian +// Macro to determine if the current machine is little endian #ifndef LITTLE_ENDIAN static const hword_t __i = 0xFFFF0000; #define LITTLE_ENDIAN ((*((byte_t *)&__i)) == 0) @@ -130,9 +130,9 @@ static const hword_t __i = 0xFFFF0000; /** @brief Convert a buffer of bytes to a half word. - @details We assume the buffer of bytes are in virtual machine byte - code format (little endian) and that they are at least HWORD_SIZE - in size. + @details It is assumed that the buffer of bytes are in virtual + machine byte code format (little endian) and that they are at least + HWORD_SIZE in size. */ hword_t convert_bytes_to_hword(const byte_t *buffer); @@ -141,17 +141,18 @@ hword_t convert_bytes_to_hword(const byte_t *buffer); endian) @param h: Half word to convert - @param buffer: Buffer to store into. We assume the buffer has at - least HWORD_SIZE space. + + @param buffer: Buffer to store into. It is assumed that the buffer + has at least HWORD_SIZE space. */ void convert_hword_to_bytes(const hword_t h, byte_t *buffer); /** @brief Convert a buffer of bytes to a word. - @details We assume the buffer of bytes are in virtual machine byte - code format (little endian) and that they are at least WORD_SIZE in - size. + @details It is assumed that the buffer of bytes are in virtual + machine byte code format (little endian) and that they are at least + WORD_SIZE in size. */ word_t convert_bytes_to_word(const byte_t *); @@ -161,13 +162,29 @@ word_t convert_bytes_to_word(const byte_t *); @param w: Word to convert - @param buffer: Buffer to store into. We assume the buffer has at - least WORD_SIZE space. + @param buffer: Buffer to store into. It is assumed that the buffer + has at least WORD_SIZE space. */ void convert_word_to_bytes(const word_t w, byte_t *buffer); +/** + @brief Swap the ordering of bytes within an half word + + @details The ordering of the bytes in the half word are reversed (4 + bytes in a half word). + + @param h: Half word to swap + */ hword_t hword_byteswap(const hword_t h); +/** + @brief Swap the ordering of bytes within an word + + @details The ordering of the bytes in the word are reversed (8 + bytes in a word). + + @param w: Word to swap + */ word_t word_byteswap(const word_t w); #endif diff --git a/lib/darr.h b/lib/darr.h index 403ec04..9e58666 100644 --- a/lib/darr.h +++ b/lib/darr.h @@ -14,7 +14,6 @@ #define DARR_H #include -#include #include "./base.h" diff --git a/vm/runtime.c b/vm/runtime.c index 1e0f20a..243cf4c 100644 --- a/vm/runtime.c +++ b/vm/runtime.c @@ -190,15 +190,21 @@ err_t vm_execute(vm_t *vm) } else if (SIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_PRINT)) { - // Steps: 1) Pop the datum 2) Figure out the format string 3) Print + /* 1) Pop + 2) Format + 3) Print + */ + // 1) figure out what datum type to pop + + // type in [0, 5] representing [byte, char, hword, int, word, + // long] int type = OPCODE_DATA_TYPE(instruction.opcode, OP_PRINT); - // Here we figure out the opcode to pop the correct datum by - // integer division of OPCODE_DATA_TYPE() by 2 as OPCODE_DATA_TYPE - // is [0,5] which under integer division by 2 maps to [0,2] where: - // 0,1 -> 0; 2,3 -> 1; 4,5 -> 2. This is exactly the map we want - // (should be obvious). + /* Byte and Char -> POP_BYTE + HWord and Int -> POP_HWORD + Word and Long -> POP_WORD + */ opcode_t pop_opcode = OP_POP_BYTE + (type / 2); data_t datum = {0}; @@ -207,11 +213,13 @@ err_t vm_execute(vm_t *vm) if (err) return err; - // TODO: Figure out a way to ensure the ordering of OP_PRINT_* - // this ordering is BYTE, CHAR, HWORD, INTEGER, WORD, LONG. - // Perhaps via static_assert + // 2) create a format string for each datum type possible - // Make a table of format strings for each data_type + // TODO: Figure out a way to ensure the ordering of OP_PRINT_* is + // exactly BYTE, CHAR, HWORD, INTEGER, WORD, LONG. Perhaps via + // static_assert + + // lookup table const char *format_strings[] = { "0x%x", "%c", @@ -228,6 +236,7 @@ err_t vm_execute(vm_t *vm) #endif }; + // 3) Print datum using the format string given. printf(format_strings[type], datum); prog->ptr++; diff --git a/vm/runtime.h b/vm/runtime.h index 0093d75..7ff96e3 100644 --- a/vm/runtime.h +++ b/vm/runtime.h @@ -67,7 +67,7 @@ static const push_f PUSH_ROUTINES[] = { [OP_PUSH_WORD] = vm_push_word, }; -/* Operations that have input determined at deserializing i.e. */ +/* Operations where operand is a word from inst_t.operand */ err_t vm_push_byte_register(vm_t *, word_t); err_t vm_push_hword_register(vm_t *, word_t); err_t vm_push_word_register(vm_t *, word_t);