From 71c633f4798c7554f3889071b85800522595029a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kn=C3=BCttel?= Date: Wed, 26 Sep 2018 13:18:37 +0200 Subject: [PATCH 01/14] added method dispatcher --- method_dispatcher.c | 120 ++++++++++++++++++++++++++++++++++ method_dispatcher.h | 61 +++++++++++++++++ test/Makefile | 14 ++++ test/method_dispatcher | Bin 0 -> 13296 bytes test/test_method_dispatcher.c | 51 +++++++++++++++ 5 files changed, 246 insertions(+) create mode 100644 method_dispatcher.c create mode 100644 method_dispatcher.h create mode 100644 test/Makefile create mode 100755 test/method_dispatcher create mode 100644 test/test_method_dispatcher.c diff --git a/method_dispatcher.c b/method_dispatcher.c new file mode 100644 index 0000000..90e4fed --- /dev/null +++ b/method_dispatcher.c @@ -0,0 +1,120 @@ +#include +#include "method_dispatcher.h" + + +dispatch_tree_t dispatch_tree_t_new(void) +{ + dispatch_tree_t tree = malloc(sizeof(struct dispatch_tree_s)); + tree->root = NULL; + return tree; +} + +void dispatch_tree_t_del(dispatch_tree_t tree) +{ + dispatch_tree_node_t_del(tree->root); + free(tree); +} + +dispatch_tree_node_t dispatch_tree_node_t_new(uint16_t word + , bci_core_method_t method) +{ + dispatch_tree_node_t node = malloc(sizeof(struct dispatch_tree_node_s)); + node->higher = NULL; + node->lower = 0; + node->method = method; + node->word = word; + return node; +} + +void dispatch_tree_node_t_del(dispatch_tree_node_t node) +{ + if(node->higher) + { + dispatch_tree_node_t_del(node->higher); + } + if(node->lower) + { + dispatch_tree_node_t_del(node->lower); + } + free(node); +} + +char dispatch_tree_t_insert(dispatch_tree_t tree + , uint16_t word + , bci_core_method_t method) +{ + dispatch_tree_node_t new_node = dispatch_tree_node_t_new(word, method); + if(!new_node) + { + return 1; + } + // explicitly handle empty tree + if(!tree->root) + { + tree->root = new_node; + return 0; + } + + // non-empty tree + dispatch_tree_node_t this_node = tree->root; + dispatch_tree_node_t parent_node = NULL; + // search for place + do + { + parent_node = this_node; + if(parent_node->word < word) + { + this_node = parent_node->higher; + continue; + } + if(parent_node->word > word) + { + this_node = parent_node->lower; + continue; + } + if(parent_node->word == word) + { + // we already have that key. + return 2; + } + + } + while(this_node); + if(parent_node->word < word) + { + parent_node->higher = new_node; + } + if(parent_node->word > word) + { + parent_node->lower = new_node; + } + + return 0; + +} + + +bci_core_method_t dispatch_tree_t_dispatch(dispatch_tree_t tree + , uint16_t word) +{ + dispatch_tree_node_t this_node = tree->root; + while(this_node) + { + if(this_node->word < word) + { + this_node = this_node->higher; + continue; + } + if(this_node->word > word) + { + this_node = this_node->lower; + continue; + } + if(this_node->word == word) + { + return this_node->method; + } + } + return NULL; +} + diff --git a/method_dispatcher.h b/method_dispatcher.h new file mode 100644 index 0000000..96a04f6 --- /dev/null +++ b/method_dispatcher.h @@ -0,0 +1,61 @@ +#ifndef bci_method_dispatcher_h__ +#define bci_method_dispatcher_h__ + +#include +#include "base.h" + +typedef struct dispatch_tree_node_s +{ + struct dispatch_tree_node_s * higher; + struct dispatch_tree_node_s * lower; + uint16_t word; + bci_core_method_t method; +} * dispatch_tree_node_t; + +typedef struct dispatch_tree_s +{ + dispatch_tree_node_t root; +} * dispatch_tree_t; + +dispatch_tree_t dispatch_tree_t_new(void); +/* + * This deletes the tree and will invoke dispatch_tree_node_t_del on + * tree->root (which will delete all the other nodes recursively). + * If you want to keep nodes you have to explicityl remove the reference to + * them by setting them to NULL. + * */ +void dispatch_tree_t_del(dispatch_tree_t tree); + + +dispatch_tree_node_t dispatch_tree_node_t_new(uint16_t word + , bci_core_method_t method); +/* + * This deletes the node an will invoke dispatch_tree_node_t_del on + * node->higher and node->lower. If you want to keep those nodes + * you have to explicitly clear the reference by setting them to NULL. + * */ +void dispatch_tree_node_t_del(dispatch_tree_node_t node); + + +/* + * Insert a new key-value-pair into the tree. + * + * Return codes: + * 0: OK + * 1: out of memory + * 2: key already in tree + * */ +char dispatch_tree_t_insert(dispatch_tree_t tree + , uint16_t word + , bci_core_method_t method); + +// TODO: +// Figure out if that function is actually useful. +// Maybe manually inserting the methods in a good order +// is better. +// +//dispatch_tree_t optimize(dispatch_tree_t tree); + +bci_core_method_t dispatch_tree_t_dispatch(dispatch_tree_t tree + , uint16_t word); +#endif diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..7997126 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,14 @@ +CC=gcc + +all: test_method_dispatcher + +method_dispatcher: clean + $(CC) ../method_dispatcher.c test_method_dispatcher.c -o method_dispatcher + +test_method_dispatcher: method_dispatcher + valgrind ./method_dispatcher + + + +clean: + -rm method_dispatcher diff --git a/test/method_dispatcher b/test/method_dispatcher new file mode 100755 index 0000000000000000000000000000000000000000..722927d6859dc0ce1721b8f7d972da01e209cc89 GIT binary patch literal 13296 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 literal 0 HcmV?d00001 diff --git a/test/test_method_dispatcher.c b/test/test_method_dispatcher.c new file mode 100644 index 0000000..563d888 --- /dev/null +++ b/test/test_method_dispatcher.c @@ -0,0 +1,51 @@ +#include +#include "../method_dispatcher.h" + +char m1(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_reg, uint16_t * reg[10], bci_stack_t * stack); +char m2(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_reg, uint16_t * reg[10], bci_stack_t * stack); +char m3(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_reg, uint16_t * reg[10], bci_stack_t * stack); +char m4(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_reg, uint16_t * reg[10], bci_stack_t * stack); +char m5(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_reg, uint16_t * reg[10], bci_stack_t * stack); + +int main(void) +{ + printf("sizeof struct dispatch_tree_node_s: %zd\n", sizeof(struct dispatch_tree_node_s)); + dispatch_tree_t tree = dispatch_tree_t_new(); + + dispatch_tree_t_insert(tree, 3 << 6, m3); + dispatch_tree_t_insert(tree, 2 << 6, m2); + dispatch_tree_t_insert(tree, 1 << 6, m1); + dispatch_tree_t_insert(tree, 4 << 6, m4); + dispatch_tree_t_insert(tree, 5 << 6, m5); + + int i; + for(i = 1; i < 6; i++) + { + dispatch_tree_t_dispatch(tree, i << 6)(i, i << 6, NULL, NULL, NULL, NULL); + } + dispatch_tree_t_del(tree); + return 0; +} + + + +char m1(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_register, uint16_t * reg[10], bci_stack_t * stack) +{ + printf("m1: %d, %d\n", small_arg, arg); +} +char m2(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_register, uint16_t * reg[10], bci_stack_t * stack) +{ + printf("m2: %d, %d\n", small_arg, arg); +} +char m3(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_register, uint16_t * reg[10], bci_stack_t * stack) +{ + printf("m3: %d, %d\n", small_arg, arg); +} +char m4(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_register, uint16_t * reg[10], bci_stack_t * stack) +{ + printf("m4: %d, %d\n", small_arg, arg); +} +char m5(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_register, uint16_t * reg[10], bci_stack_t * stack) +{ + printf("m5: %d, %d\n", small_arg, arg); +} From 0d8cb5df7c749fd662a0db5088391d786642b326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kn=C3=BCttel?= Date: Wed, 26 Sep 2018 17:47:22 +0200 Subject: [PATCH 02/14] moved method_dispatcher to subdirectory --- .../method_dispatcher.c | 0 .../method_dispatcher.h | 0 {test => method_dispatcher/test}/Makefile | 0 .../test/test_method_dispatcher.c | 51 ++++++++++++++++++ test/method_dispatcher | Bin 13296 -> 0 bytes test/test_method_dispatcher.c | 51 ------------------ 6 files changed, 51 insertions(+), 51 deletions(-) rename method_dispatcher.c => method_dispatcher/method_dispatcher.c (100%) rename method_dispatcher.h => method_dispatcher/method_dispatcher.h (100%) rename {test => method_dispatcher/test}/Makefile (100%) create mode 100644 method_dispatcher/test/test_method_dispatcher.c delete mode 100755 test/method_dispatcher delete mode 100644 test/test_method_dispatcher.c diff --git a/method_dispatcher.c b/method_dispatcher/method_dispatcher.c similarity index 100% rename from method_dispatcher.c rename to method_dispatcher/method_dispatcher.c diff --git a/method_dispatcher.h b/method_dispatcher/method_dispatcher.h similarity index 100% rename from method_dispatcher.h rename to method_dispatcher/method_dispatcher.h diff --git a/test/Makefile b/method_dispatcher/test/Makefile similarity index 100% rename from test/Makefile rename to method_dispatcher/test/Makefile diff --git a/method_dispatcher/test/test_method_dispatcher.c b/method_dispatcher/test/test_method_dispatcher.c new file mode 100644 index 0000000..ae1fff0 --- /dev/null +++ b/method_dispatcher/test/test_method_dispatcher.c @@ -0,0 +1,51 @@ +#include +#include "../method_dispatcher.h" + +char m1(uint8_t small_arg, void * state); +char m2(uint8_t small_arg, void * state); +char m3(uint8_t small_arg, void * state); +char m4(uint8_t small_arg, void * state); +char m5(uint8_t small_arg, void * state); + +int main(void) +{ + printf("sizeof struct dispatch_tree_node_s: %zd\n", sizeof(struct dispatch_tree_node_s)); + dispatch_tree_t tree = dispatch_tree_t_new(); + + dispatch_tree_t_insert(tree, 3 << 6, m3); + dispatch_tree_t_insert(tree, 2 << 6, m2); + dispatch_tree_t_insert(tree, 1 << 6, m1); + dispatch_tree_t_insert(tree, 4 << 6, m4); + dispatch_tree_t_insert(tree, 5 << 6, m5); + + int i; + for(i = 1; i < 6; i++) + { + dispatch_tree_t_dispatch(tree, i << 6)(i, NULL); + } + dispatch_tree_t_del(tree); + return 0; +} + + + +char m1(uint8_t small_arg, void * state) +{ + printf("m1: %d\n", small_arg); +} +char m2(uint8_t small_arg, void * state) +{ + printf("m2: %d\n", small_arg); +} +char m3(uint8_t small_arg, void * state) +{ + printf("m3: %d\n", small_arg); +} +char m4(uint8_t small_arg, void * state) +{ + printf("m4: %d\n", small_arg); +} +char m5(uint8_t small_arg, void * state) +{ + printf("m5: %d\n", small_arg); +} diff --git a/test/method_dispatcher b/test/method_dispatcher deleted file mode 100755 index 722927d6859dc0ce1721b8f7d972da01e209cc89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13296 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 diff --git a/test/test_method_dispatcher.c b/test/test_method_dispatcher.c deleted file mode 100644 index 563d888..0000000 --- a/test/test_method_dispatcher.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include "../method_dispatcher.h" - -char m1(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_reg, uint16_t * reg[10], bci_stack_t * stack); -char m2(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_reg, uint16_t * reg[10], bci_stack_t * stack); -char m3(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_reg, uint16_t * reg[10], bci_stack_t * stack); -char m4(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_reg, uint16_t * reg[10], bci_stack_t * stack); -char m5(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_reg, uint16_t * reg[10], bci_stack_t * stack); - -int main(void) -{ - printf("sizeof struct dispatch_tree_node_s: %zd\n", sizeof(struct dispatch_tree_node_s)); - dispatch_tree_t tree = dispatch_tree_t_new(); - - dispatch_tree_t_insert(tree, 3 << 6, m3); - dispatch_tree_t_insert(tree, 2 << 6, m2); - dispatch_tree_t_insert(tree, 1 << 6, m1); - dispatch_tree_t_insert(tree, 4 << 6, m4); - dispatch_tree_t_insert(tree, 5 << 6, m5); - - int i; - for(i = 1; i < 6; i++) - { - dispatch_tree_t_dispatch(tree, i << 6)(i, i << 6, NULL, NULL, NULL, NULL); - } - dispatch_tree_t_del(tree); - return 0; -} - - - -char m1(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_register, uint16_t * reg[10], bci_stack_t * stack) -{ - printf("m1: %d, %d\n", small_arg, arg); -} -char m2(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_register, uint16_t * reg[10], bci_stack_t * stack) -{ - printf("m2: %d, %d\n", small_arg, arg); -} -char m3(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_register, uint16_t * reg[10], bci_stack_t * stack) -{ - printf("m3: %d, %d\n", small_arg, arg); -} -char m4(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_register, uint16_t * reg[10], bci_stack_t * stack) -{ - printf("m4: %d, %d\n", small_arg, arg); -} -char m5(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_register, uint16_t * reg[10], bci_stack_t * stack) -{ - printf("m5: %d, %d\n", small_arg, arg); -} From a515b56f584e3c39926336727408fda09d135909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kn=C3=BCttel?= Date: Wed, 26 Sep 2018 17:48:03 +0200 Subject: [PATCH 03/14] moved method_dispatcher to subdirectory --- method_dispatcher/method_dispatcher.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/method_dispatcher/method_dispatcher.h b/method_dispatcher/method_dispatcher.h index 96a04f6..fb40436 100644 --- a/method_dispatcher/method_dispatcher.h +++ b/method_dispatcher/method_dispatcher.h @@ -2,7 +2,7 @@ #define bci_method_dispatcher_h__ #include -#include "base.h" +#include "../base.h" typedef struct dispatch_tree_node_s { From e9801283e220088bf5765205c58de5f9ec584087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kn=C3=BCttel?= Date: Wed, 26 Sep 2018 17:50:12 +0200 Subject: [PATCH 04/14] initial interpreter, base and stack --- base.h | 20 ++++++ interpreter/interpreter.c | 145 ++++++++++++++++++++++++++++++++++++++ interpreter/interpreter.h | 79 +++++++++++++++++++++ stack.c | 26 +++++++ stack.h | 14 ++++ 5 files changed, 284 insertions(+) create mode 100644 base.h create mode 100644 interpreter/interpreter.c create mode 100644 interpreter/interpreter.h create mode 100644 stack.c create mode 100644 stack.h diff --git a/base.h b/base.h new file mode 100644 index 0000000..31c918f --- /dev/null +++ b/base.h @@ -0,0 +1,20 @@ +#ifndef bci_base_h__ +#define bci_base_h__ +#include +#include "stack.h" + +#define BCI_CORE_NUM_REG 40 + +// Note that void * state will later be casted to +// machine_state_t. +typedef char (* bci_core_method_t)(uint8_t small_arg + , void * state); + + +#define BCI_CORE_RESULT_RESERVED_BITS 0b11000000 +#define BCI_CORE_RESULT_APPLICATION_BITS 0b00111111 + +#define BCI_CORE_SMALL_ARG_MASK 0b0000000000111111 +#define BCI_CORE_OPCODE_MASK 0b1111111111000000 + +#endif diff --git a/interpreter/interpreter.c b/interpreter/interpreter.c new file mode 100644 index 0000000..5b87998 --- /dev/null +++ b/interpreter/interpreter.c @@ -0,0 +1,145 @@ +#include + +#include "interpreter.h" + + + +machine_state_t machine_state_t_new( void * cache_function_data + , size_t cache_size + , size_t (* cache_block)(uint16_t * cache + , uint16_t offset + , size_t cache_size + , void * cache_function_data) + , dispatch_tree_t method_dispatcher) +{ + machine_state_t state = malloc(sizeof(struct machine_state_s)); + if(!state) + { + return NULL; + } + uint16_t * cache = calloc(sizeof(uint16_t), cache_size); + if(!cache) + { + free(state); + return NULL; + } + + state->cache = cache; + state->cache_block = cache_block; + state->cache_size = cache_size; + state->cache_loaded = 0; + state->cache_function_data = cache_function_data; + + state->program_counter = 0; + state->status_reg = 0; + state->shutdown_reg = 0; + int i; + for(i = 0; i < BCI_CORE_NUM_REG; i++) + { + state->data_reg[BCI_CORE_NUM_REG] = 0; + } + state->stack = NULL; + + state->method_dispatcher = method_dispatcher; + + return state; +} + +void machine_state_t_del(machine_state_t state) +{ + free(state->cache); + dispatch_tree_t_del(state->method_dispatcher); + free(state); +} + + +char update_cache(machine_state_t state) +{ + // Calculate a clever offset for caching. + uint16_t cache_offset = state->program_counter; + if((cache_offset + state->cache_size) + > state->program_size) + { + if(state->program_size < state->cache_size) + { + cache_offset = 0; + } + else + { + cache_offset = state->program_size - state->cache_size; + } + } + size_t cached = state->cache_block(state->cache + , cache_offset + , state->cache_size + , state->cache_function_data); + + if(cached != state->cache_size) + { + return 1; + } + return 0; +} + +char machine_state_t_exec_cycle(machine_state_t state) +{ + uint16_t opcode, arg; + + // This would be bad. + if(state->program_counter >= state->program_size) + { + return 0b01000000 | 1; + } + + // Calculate the in-cache offset of the program counter. + int32_t offset = state->program_counter - state->cache_offset; + + // Check if we need to update the cache. + if( offset < 0 + || !(state->cache_loaded) + // Note: + // +1 for cache starting with 0 + // +1 for the argument + || (offset + 2) > state->cache_size) + { + if(update_cache(state)) + { + return 0b01000000 | 2; + } + // Re-calculate the in-cache offset + offset = state->program_counter - state->cache_offset; + } + + // Check if the argument is cached. + if(offset + 2 > state->cache_size) + { + // Because we have cached the program memory above + // there is no way that we can include the argument + // now. There is something wrong. + return 0b01000000 | 3; + } + + opcode = state->cache[offset]; + arg = state->cache[offset + 1]; + + bci_core_method_t method = dispatch_tree_t_dispatch( + state->method_dispatcher + , opcode & BCI_CORE_OPCODE_MASK); + if(!method) + { + return 0b10000000 | 1; + } + + return BCI_CORE_RESULT_APPLICATION_BITS + & method(arg + , opcode & BCI_CORE_SMALL_ARG_MASK + , state); + +} + + +char machine_state_t_default_afterexec(machine_state_t state, uint8_t argc) +{ + state->program_counter += 1 + argc; + return 0; +} diff --git a/interpreter/interpreter.h b/interpreter/interpreter.h new file mode 100644 index 0000000..b9213ed --- /dev/null +++ b/interpreter/interpreter.h @@ -0,0 +1,79 @@ +#ifndef bci_interpreter_h__ +#define bci_interpreter_h__ + +#include +#include "base.h" +#include "method_dispatcher.h" +#include "stack.h" + +typedef machine_state_s +{ + // The size of the program in 16-bit words + uint16_t program_size; + void * cache_function_data; + + size_t cache_size; + uint16_t cache_offset; + uint16_t * cache; + size_t (* cache_block)(uint16_t * cache + , uint16_t offset + , size_t cache_size + , void * cache_function_data); + char cache_loaded; + + uint16_t program_counter; + uint16_t status_reg; + // Any non-zero value in this register will + // break the program execution. + uint16_t shutdown_reg; + uint16_t data_reg[BCI_CORE_NUM_REG]; + bci_stack_t stack; + + + dispatch_tree_t method_dispatcher; + +} * machine_state_t; + +machine_state_t machine_state_t_new( void * cache_function_data + , size_t cache_size + , size_t (* cache_block)(uint16_t * cache + , uint16_t offset + , size_t cache_size + , void * cache_function_data) + , dispatch_tree_t method_dispatcher); + +void machine_state_t_del(machine_state_t state); + +/* + * This function essentially executes one cycle of the machine execution. + * It will fetch the opcode and argument, dispatch the method and execute it. + * + * Also this will update the cache if needed. + * + * Possible return codes: + * + * - 0bxyXXXXXX + * Error while executing the cycle. + * - 0b01XXXXXX + * Error in the internal memory management (i.e. program counter out + * of bounds) + * - 0b01000000 | 1: program_counter > program_size + * - 0b01000000 | 2: failed to cache new data + * - 0b01000000 | 3: argument is out of program bounds + * + * - 0b10XXXXXX + * Error while dispatching the method + * - 0b10000000 | 1: unknown opcode + * + * - 0b00XXXXXX + * XXXXXX is the return value of the bci_core_method_t method. + * */ +char machine_state_t_exec_cycle(machine_state_t state); + +/* + * Do the default updates on the machine state. + * This will be basically increasing the program counter. + * */ +char machine_state_t_default_afterexec(machine_state_t state, uint8_t argc); + +#endif diff --git a/stack.c b/stack.c new file mode 100644 index 0000000..706ae7d --- /dev/null +++ b/stack.c @@ -0,0 +1,26 @@ +#include +#include "stack.h" + +char bci_stack_t_push(bci_stack_t * stack, uint16_t value) +{ + bci_stack_t node = malloc(sizeof(struct bci_stack_s)); + if(!node) + { + return 1; + } + node->next = *stack; + node->value = value; + stack = &node; + return 0; +} +char bci_stack_t_pop(bci_stack_t * stack, uint16_t * result) +{ + if(!*stack) + { + return 1; + } + *result = (*stack)->value; + *stack = (*stack)->next; + return 0; +} + diff --git a/stack.h b/stack.h new file mode 100644 index 0000000..894790e --- /dev/null +++ b/stack.h @@ -0,0 +1,14 @@ +#ifndef bci_stack_h__ +#define bci_stack_h__ + +#include + +typedef struct bci_stack_s +{ + struct bci_stack_s * next; + uint16_t value; +} * bci_stack_t; + +char bci_stack_t_push(bci_stack_t * stack, uint16_t value); +char bci_stack_t_pop(bci_stack_t * stack, uint16_t * result); +#endif From 712ff65af4e00ebf7703fa6e4be9170a3849db8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kn=C3=BCttel?= Date: Wed, 26 Sep 2018 18:22:36 +0200 Subject: [PATCH 05/14] added and fixed stack --- method_dispatcher/test/Makefile | 2 +- stack.c | 20 +++++++++++++++++--- stack.h | 6 ++++++ test/Makefile | 12 ++++++++++++ test/test_stack.c | 29 +++++++++++++++++++++++++++++ 5 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 test/Makefile create mode 100644 test/test_stack.c diff --git a/method_dispatcher/test/Makefile b/method_dispatcher/test/Makefile index 7997126..c9fc7c9 100644 --- a/method_dispatcher/test/Makefile +++ b/method_dispatcher/test/Makefile @@ -3,7 +3,7 @@ CC=gcc all: test_method_dispatcher method_dispatcher: clean - $(CC) ../method_dispatcher.c test_method_dispatcher.c -o method_dispatcher + $(CC) -g ../method_dispatcher.c test_method_dispatcher.c -o method_dispatcher test_method_dispatcher: method_dispatcher valgrind ./method_dispatcher diff --git a/stack.c b/stack.c index 706ae7d..97d4a8c 100644 --- a/stack.c +++ b/stack.c @@ -10,17 +10,31 @@ char bci_stack_t_push(bci_stack_t * stack, uint16_t value) } node->next = *stack; node->value = value; - stack = &node; + *stack = node; return 0; } char bci_stack_t_pop(bci_stack_t * stack, uint16_t * result) { + bci_stack_t this_node; if(!*stack) { return 1; } - *result = (*stack)->value; - *stack = (*stack)->next; + this_node = *stack; + *result = this_node->value; + *stack = this_node->next; + free(this_node); return 0; } +void bci_stack_t_del(bci_stack_t * stack) +{ + bci_stack_t this_node; + + while(*stack) + { + this_node = *stack; + *stack = this_node->next; + free(this_node); + } +} diff --git a/stack.h b/stack.h index 894790e..0522db0 100644 --- a/stack.h +++ b/stack.h @@ -11,4 +11,10 @@ typedef struct bci_stack_s char bci_stack_t_push(bci_stack_t * stack, uint16_t value); char bci_stack_t_pop(bci_stack_t * stack, uint16_t * result); + +/* + * Deletes the entire (!) stack. + * + * */ +void bci_stack_t_del(bci_stack_t * stack); #endif diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..a90518d --- /dev/null +++ b/test/Makefile @@ -0,0 +1,12 @@ +CC=gcc + +all: test_stack + +stack: clean + $(CC) -g ../stack.c test_stack.c -o stack + +test_stack: stack + valgrind ./stack + +clean: + -rm stack diff --git a/test/test_stack.c b/test/test_stack.c new file mode 100644 index 0000000..05fecc1 --- /dev/null +++ b/test/test_stack.c @@ -0,0 +1,29 @@ +#include +#include "../stack.h" + +int main(void) +{ + bci_stack_t stack = NULL; + int i; + uint16_t res; + char status = 0; + + + for(i = 0; i < 10; i++) + { + bci_stack_t_push(&stack, (uint16_t) i); + } + while(!status) + { + status = bci_stack_t_pop(&stack, &res); + printf("%d\n", res); + } + + + for(i = 0; i < 10; i++) + { + bci_stack_t_push(&stack, (uint16_t) i); + } + bci_stack_t_del(&stack); + return 0; +} From 59012a41b7cab2677989cca12338f8f5eee14016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kn=C3=BCttel?= Date: Thu, 27 Sep 2018 11:26:20 +0200 Subject: [PATCH 06/14] added autoinserter for the dispatch tree --- method_dispatcher/method_dispatcher.c | 38 +++++++++++++++++++ method_dispatcher/method_dispatcher.h | 38 ++++++++++++++++--- .../test/test_method_dispatcher.c | 12 ++++++ 3 files changed, 82 insertions(+), 6 deletions(-) diff --git a/method_dispatcher/method_dispatcher.c b/method_dispatcher/method_dispatcher.c index 90e4fed..e26c553 100644 --- a/method_dispatcher/method_dispatcher.c +++ b/method_dispatcher/method_dispatcher.c @@ -118,3 +118,41 @@ bci_core_method_t dispatch_tree_t_dispatch(dispatch_tree_t tree return NULL; } +dispatch_tree_autoinserter_t dispatch_tree_autoinserter_t_new(dispatch_tree_t tree) +{ + dispatch_tree_autoinserter_t autoinserter = malloc( + sizeof(struct dispatch_tree_autoinserter_s)); + if(!autoinserter) + { + return NULL; + } + autoinserter->mayor = 2; + autoinserter->minor = 1; + autoinserter->tree = tree; + return autoinserter; +} + +void dispatch_tree_autoinserter_t_del(dispatch_tree_autoinserter_t autoinserter) +{ + free(autoinserter); +} + + +uint16_t dispatch_tree_autoinserter_t_insert( + dispatch_tree_autoinserter_t autoinserter + , bci_core_method_t method) +{ + uint16_t opcode = 0b1111111111; + opcode *= autoinserter->minor; + opcode /= autoinserter->mayor; + opcode <<= 6; + + dispatch_tree_t_insert(autoinserter->tree, opcode, method); + + autoinserter->minor = (autoinserter->minor + 2) % autoinserter->mayor; + if(autoinserter->minor == 1) + { + autoinserter->mayor *= 2; + } + return opcode; +} diff --git a/method_dispatcher/method_dispatcher.h b/method_dispatcher/method_dispatcher.h index fb40436..6b6dac9 100644 --- a/method_dispatcher/method_dispatcher.h +++ b/method_dispatcher/method_dispatcher.h @@ -49,13 +49,39 @@ char dispatch_tree_t_insert(dispatch_tree_t tree , uint16_t word , bci_core_method_t method); -// TODO: -// Figure out if that function is actually useful. -// Maybe manually inserting the methods in a good order -// is better. -// -//dispatch_tree_t optimize(dispatch_tree_t tree); bci_core_method_t dispatch_tree_t_dispatch(dispatch_tree_t tree , uint16_t word); + + + +typedef struct dispatch_tree_autoinserter_s +{ + uint16_t mayor; + uint16_t minor; + dispatch_tree_t tree; +} * dispatch_tree_autoinserter_t; + +dispatch_tree_autoinserter_t dispatch_tree_autoinserter_t_new(dispatch_tree_t tree); +void dispatch_tree_autoinserter_t_del(dispatch_tree_autoinserter_t autoinserter); + +/* + * This function inserts a new method into the tree and automatically + * chooses the optimal word to prevent degeneration. + * + * NOTE: + * When inserting mutliple methods this function acts deterministic, + * IF AND ONLY IF the order of the methods is not changed. + * + * The assembler will bring an analogous function that allows one + * to determine the opcodes of the methods. + * + * NOTE: + * This algorithm will not work for more that 1023 registered opcodes. + * This limit is however considered acceptable. + * + * */ +uint16_t dispatch_tree_autoinserter_t_insert( + dispatch_tree_autoinserter_t autoinserter + , bci_core_method_t method); #endif diff --git a/method_dispatcher/test/test_method_dispatcher.c b/method_dispatcher/test/test_method_dispatcher.c index ae1fff0..917e901 100644 --- a/method_dispatcher/test/test_method_dispatcher.c +++ b/method_dispatcher/test/test_method_dispatcher.c @@ -24,6 +24,18 @@ int main(void) dispatch_tree_t_dispatch(tree, i << 6)(i, NULL); } dispatch_tree_t_del(tree); + + + bci_core_method_t methods[5] = {m1, m2, m3, m4, m5}; + tree = dispatch_tree_t_new(); + dispatch_tree_autoinserter_t inserter = dispatch_tree_autoinserter_t_new(tree); + for(i = 0; i < 5; i++) + { + printf("%u\n", dispatch_tree_autoinserter_t_insert(inserter, methods[i])); + } + dispatch_tree_autoinserter_t_del(inserter); + dispatch_tree_t_del(tree); + return 0; } From 6612918cf7793082a46d773d127cffacbf7e7d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kn=C3=BCttel?= Date: Wed, 3 Oct 2018 23:26:02 +0200 Subject: [PATCH 07/14] fixed core methods and added test --- interpreter/core_methods.c | 360 ++++++++++++++++++++++++++++ interpreter/core_methods.h | 110 +++++++++ interpreter/test/Makefile | 14 ++ interpreter/test/test_interpreter.c | 64 +++++ 4 files changed, 548 insertions(+) create mode 100644 interpreter/core_methods.c create mode 100644 interpreter/core_methods.h create mode 100644 interpreter/test/Makefile create mode 100644 interpreter/test/test_interpreter.c diff --git a/interpreter/core_methods.c b/interpreter/core_methods.c new file mode 100644 index 0000000..b63a863 --- /dev/null +++ b/interpreter/core_methods.c @@ -0,0 +1,360 @@ +#include "core_methods.h" + +#define BCI_CORE_REGISTER_CHECK(var) if(var > BCI_CORE_NUM_REG) return 1 + +// #1 -> $0 +char bci_cm_ldi(uint8_t small_arg, machine_state_t state) +{ + BCI_CORE_REGISTER_CHECK(small_arg); + + uint16_t arg; + char res; + res = machine_state_t_get_word(state, state->program_counter + 1, &arg); + if(res) + { + return res; + } + + state->data_reg[small_arg] = arg; + + return machine_state_t_default_afterexec(state, 1); +} + +// @1 -> $0 +char bci_cm_ld(uint8_t small_arg, machine_state_t state) +{ + BCI_CORE_REGISTER_CHECK(small_arg); + + uint16_t arg; + char res; + res = machine_state_t_get_word(state, state->program_counter + 1, &arg); + if(res) + { + return res; + } + + res = machine_state_t_get_mem(state, arg, &arg); + if(res) + { + return res; + } + state->data_reg[small_arg] = arg; + + return machine_state_t_default_afterexec(state, 1); +} + +// $0 -> @1 +char bci_cm_st(uint8_t small_arg, machine_state_t state) +{ + BCI_CORE_REGISTER_CHECK(small_arg); + char res; + + uint16_t arg; + res = machine_state_t_get_word(state, state->program_counter + 1, &arg); + if(res) + { + return res; + } + + res = machine_state_t_set_mem(state, arg, state->data_reg[small_arg]); + if(res) + { + return res; + } + + return machine_state_t_default_afterexec(state, 1); +} + +// $0 + 1 -> $0 +char bci_cm_inc(uint8_t small_arg, machine_state_t state) +{ + int32_t result; + BCI_CORE_REGISTER_CHECK(small_arg); + result = state->data_reg[small_arg] + 1; + state->data_reg[small_arg] = result & 0xffff; + state->status_reg = result >> 16; + return machine_state_t_default_afterexec(state, 0); +} + +// $0 - 1 -> $0 +char bci_cm_dec(uint8_t small_arg, machine_state_t state) +{ + BCI_CORE_REGISTER_CHECK(small_arg); + int32_t result = state->data_reg[small_arg] - 1; + state->data_reg[small_arg] = result & 0xffff; + state->status_reg = result >> 16; + return machine_state_t_default_afterexec(state, 0); +} + +// $0 + $1 -> $0 +char bci_cm_add(uint8_t small_arg, machine_state_t state) +{ + BCI_CORE_REGISTER_CHECK(small_arg); + uint16_t arg; + char res; + res = machine_state_t_get_word(state, state->program_counter + 1, &arg); + if(res) + { + return res; + } + + BCI_CORE_REGISTER_CHECK(arg); + int32_t result = state->data_reg[small_arg] + state->data_reg[arg]; + state->data_reg[small_arg] = result & 0xffff; + state->status_reg = result >> 16; + + return machine_state_t_default_afterexec(state, 1); +} + + +// $0 - $1 -> $0 +char bci_cm_sub(uint8_t small_arg, machine_state_t state) +{ + BCI_CORE_REGISTER_CHECK(small_arg); + uint16_t arg; + char res; + res = machine_state_t_get_word(state, state->program_counter + 1, &arg); + if(res) + { + return res; + } + + BCI_CORE_REGISTER_CHECK(arg); + int32_t result = state->data_reg[small_arg] - state->data_reg[arg]; + + state->data_reg[small_arg] = result & 0xffff; + state->status_reg = result >> 16; + + return machine_state_t_default_afterexec(state, 1); +} + + +// $0 * $1 -> $0 +char bci_cm_mul(uint8_t small_arg, machine_state_t state) +{ + BCI_CORE_REGISTER_CHECK(small_arg); + uint16_t arg; + char res; + res = machine_state_t_get_word(state, state->program_counter + 1, &arg); + if(res) + { + return res; + } + + BCI_CORE_REGISTER_CHECK(arg); + int32_t result = state->data_reg[small_arg] * state->data_reg[arg]; + state->data_reg[small_arg] = result & 0xffff; + state->status_reg = result >> 16; + return machine_state_t_default_afterexec(state, 1); +} + +// $0 / $1 -> $0 +char bci_cm_div(uint8_t small_arg, machine_state_t state) +{ + BCI_CORE_REGISTER_CHECK(small_arg); + uint16_t arg; + char res; + res = machine_state_t_get_word(state, state->program_counter + 1, &arg); + if(res) + { + return res; + } + + BCI_CORE_REGISTER_CHECK(arg); + int32_t result = state->data_reg[small_arg] / state->data_reg[arg]; + state->data_reg[small_arg] = result & 0xffff; + state->status_reg = result >> 16; + return machine_state_t_default_afterexec(state, 1); +} + + +// if($0 > 0): 1 -> $st_reg +// else: 0 -> $st_reg +char bci_cm_gt(uint8_t small_arg, machine_state_t state) +{ + BCI_CORE_REGISTER_CHECK(small_arg); + + if(state->data_reg[small_arg] > 0) + { + state->status_reg = 1; + } + else + { + state->status_reg = 0; + } + return machine_state_t_default_afterexec(state, 0); +} + +// if($0 >= 0): 1 -> $st_reg +// else: 0 -> $st_reg +char bci_cm_ge(uint8_t small_arg, machine_state_t state) +{ + BCI_CORE_REGISTER_CHECK(small_arg); + + if(state->data_reg[small_arg] >= 0) + { + state->status_reg = 1; + } + else + { + state->status_reg = 0; + } + return machine_state_t_default_afterexec(state, 0); +} +// if($0 < 0): 1 -> $st_reg +// else: 0 -> $st_reg +char bci_cm_lt(uint8_t small_arg, machine_state_t state) +{ + BCI_CORE_REGISTER_CHECK(small_arg); + + if(state->data_reg[small_arg] < 0) + { + state->status_reg = 1; + } + else + { + state->status_reg = 0; + } + return machine_state_t_default_afterexec(state, 0); +} +// if($0 <= 0): 1 -> $st_reg +// else: 0 -> $st_reg +char bci_cm_le(uint8_t small_arg, machine_state_t state) +{ + BCI_CORE_REGISTER_CHECK(small_arg); + + if(state->data_reg[small_arg] <= 0) + { + state->status_reg = 1; + } + else + { + state->status_reg = 0; + } + return machine_state_t_default_afterexec(state, 0); +} +// if($0 == 0): 1 -> $st_reg +// else: 0 -> $st_reg +char bci_cm_eq(uint8_t small_arg, machine_state_t state) +{ + BCI_CORE_REGISTER_CHECK(small_arg); + + if(state->data_reg[small_arg] == 0) + { + state->status_reg = 1; + } + else + { + state->status_reg = 0; + } + return machine_state_t_default_afterexec(state, 0); +} + +// #1 -> $pc; 0 -> $st_reg +char bci_cm_jmp(uint8_t small_arg, machine_state_t state) +{ + uint16_t arg; + char res = machine_state_t_get_word(state, state->program_counter + 1, &arg); + + if(res) + { + return res; + } + + state->program_counter = arg; + return 0; +} + +// if($st_reg): #1 -> $pc; 0 -> $st_reg +// else: do nothing +char bci_cm_cjmp(uint8_t small_arg, machine_state_t state) +{ + uint16_t arg; + char res = machine_state_t_get_word(state, state->program_counter + 1, &arg); + + if(res) + { + return res; + } + + if(state->status_reg) + { + state->program_counter = arg; + return 0; + } + + return machine_state_t_default_afterexec(state, 1); +} +// $pc -> @stack +// #1 -> $pc +char bci_cm_call(uint8_t small_arg, machine_state_t state) +{ + uint16_t arg; + char res = machine_state_t_get_word(state, state->program_counter + 1, &arg); + + if(res) + { + return res; + } + + res = bci_stack_t_push(&(state->stack), state->program_counter); + if(res) + { + return res; + } + state->program_counter = arg; + return 0; +} +// if($st_reg): $pc -> @stack; #1 -> $pc; 0 -> $st_reg +// else: do nothing +char bci_cm_ccall(uint8_t small_arg, machine_state_t state) +{ + uint16_t arg; + char res = machine_state_t_get_word(state, state->program_counter + 1, &arg); + + if(res) + { + return res; + } + + if(state->status_reg) + { + state->program_counter = arg; + res = bci_stack_t_push(&(state->stack), state->program_counter); + if(res) + { + return res; + } + return 0; + } + + return machine_state_t_default_afterexec(state, 1); +} +// @stack -> $pc +char bci_cm_ret(uint8_t small_arg, machine_state_t state) +{ + uint16_t result; + char res = bci_stack_t_pop(&(state->stack), &result); + if(res) + { + return res; + } + + state->program_counter = result; + return 0; +} + +// 0 -> $st_reg +char bci_cm_cl(uint8_t small_arg, machine_state_t state) +{ + state->status_reg = 0; + return machine_state_t_default_afterexec(state, 0); +} + +// 1 -> $su_reg +char bci_cm_stop(uint8_t small_arg, machine_state_t state) +{ + state->shutdown_reg = 0; + return machine_state_t_default_afterexec(state, 0); +} + diff --git a/interpreter/core_methods.h b/interpreter/core_methods.h new file mode 100644 index 0000000..b7fdd08 --- /dev/null +++ b/interpreter/core_methods.h @@ -0,0 +1,110 @@ +#ifndef bci_core_methods_h__ +#define bci_core_methods_h__ +#include "interpreter.h" + + +/* + * This library brings a set of essential core methods. + * */ + + +/* + * Naming conventions: + * + * x = 0, 1, 2, 3...: arguments. + * 0: small_arg (6 bit) + * 1, 2, ...: 16 bit optional arguments + * + * $x: value of data register x + * @x: value of memory word x + * #x: value of argument x + * 0, 1, 2, ...: integer 0, 1, 2, ... + * + * -> write result in register/word on the right + * + * st_reg: status register + * su_reg: shutdown register + * pc: program counter + * + * stack: the builtin stack + * */ + +// #1 -> $0 +char bci_cm_ldi(uint8_t small_arg, machine_state_t state); + +// @1 -> $0 +char bci_cm_ld(uint8_t small_arg, machine_state_t state); + +// $0 -> @1 +char bci_cm_st(uint8_t small_arg, machine_state_t state); + + +// NOTES on inc, dec, add, sub, mul, div: +// +// These methods will store the overflow-word in $st_reg. + + +// $0 + 1 -> $0 +char bci_cm_inc(uint8_t small_arg, machine_state_t state); + +// $0 - 1 -> $0 +char bci_cm_dec(uint8_t small_arg, machine_state_t state); + +// $0 + $1 -> $0 +char bci_cm_add(uint8_t small_arg, machine_state_t state); + +// $0 - $1 -> $0 +char bci_cm_sub(uint8_t small_arg, machine_state_t state); + +// $0 * $1 -> $0 +char bci_cm_mul(uint8_t small_arg, machine_state_t state); + +// $0 / $1 -> $0 +char bci_cm_div(uint8_t small_arg, machine_state_t state); + +// if($0 > 0): 1 -> $st_reg +// else: 0 -> $st_reg +char bci_cm_gt(uint8_t small_arg, machine_state_t state); + +// if($0 >= 0): 1 -> $st_reg +// else: 0 -> $st_reg +char bci_cm_ge(uint8_t small_arg, machine_state_t state); + +// if($0 < 0): 1 -> $st_reg +// else: 0 -> $st_reg +char bci_cm_lt(uint8_t small_arg, machine_state_t state); + +// if($0 <= 0): 1 -> $st_reg +// else: 0 -> $st_reg +char bci_cm_le(uint8_t small_arg, machine_state_t state); + +// if($0 == 0): 1 -> $st_reg +// else: 0 -> $st_reg +char bci_cm_eq(uint8_t small_arg, machine_state_t state); + +// #1 -> $pc +char bci_cm_jmp(uint8_t small_arg, machine_state_t state); + +// if($st_reg): #1 -> $pc +// else: do nothing +char bci_cm_cjmp(uint8_t small_arg, machine_state_t state); + +// $pc -> @stack +// #1 -> $pc +char bci_cm_call(uint8_t small_arg, machine_state_t state); + +// if($st_reg): $pc -> @stack; #1 -> $pc +// else: do nothing +char bci_cm_ccall(uint8_t small_arg, machine_state_t state); + +// @stack -> $pc +char bci_cm_ret(uint8_t small_arg, machine_state_t state); + +// 0 -> $st_reg +char bci_cm_cl(uint8_t small_arg, machine_state_t state); + +// 1 -> $su_reg +char bci_cm_stop(uint8_t small_arg, machine_state_t state); + + +#endif diff --git a/interpreter/test/Makefile b/interpreter/test/Makefile new file mode 100644 index 0000000..6703b38 --- /dev/null +++ b/interpreter/test/Makefile @@ -0,0 +1,14 @@ +CC=gcc + +all: test_interpreter + +interpreter: clean + $(CC) -g ../../stack.c ../interpreter.c ../core_methods.c ../../method_dispatcher/method_dispatcher.c test_interpreter.c -o interpreter + +test_interpreter: interpreter + valgrind ./interpreter + + + +clean: + diff --git a/interpreter/test/test_interpreter.c b/interpreter/test/test_interpreter.c new file mode 100644 index 0000000..5793f0c --- /dev/null +++ b/interpreter/test/test_interpreter.c @@ -0,0 +1,64 @@ +#include +#include +#include "../interpreter.h" +#include "../core_methods.h" +#include "../../method_dispatcher/method_dispatcher.h" + +size_t copy_cache(uint16_t * cache + , uint16_t offset + , size_t cache_size + , void * cache_function_data); + +int main(void) +{ + dispatch_tree_t tree = dispatch_tree_t_new(); + dispatch_tree_autoinserter_t inserter = dispatch_tree_autoinserter_t_new(tree); + uint16_t ldi = dispatch_tree_autoinserter_t_insert(inserter, (bci_core_method_t) bci_cm_ldi); + uint16_t add = dispatch_tree_autoinserter_t_insert(inserter, (bci_core_method_t) bci_cm_add); + + uint16_t * program = calloc(sizeof(uint16_t), 20); + program[0] = ldi; + program[1] = 0xfefe; + program[2] = ldi | 1; + program[3] = 2; + program[4] = ldi | 2; + program[5] = 3; + program[6] = add | 1; + program[7] = 2; + + machine_state_t state = machine_state_t_new( + program + , 8 + , 20 + , 20 + , copy_cache + , tree); + + machine_state_t_exec_cycle(state); + machine_state_t_exec_cycle(state); + machine_state_t_exec_cycle(state); + machine_state_t_exec_cycle(state); + printf("data_reg[0]: %x\n", state->data_reg[0]); + printf("data_reg[1]: %x\n", state->data_reg[1]); + printf("data_reg[2]: %x\n", state->data_reg[2]); + printf("program_counter: %d\n", state->program_counter); + dispatch_tree_autoinserter_t_del(inserter); + machine_state_t_del(state); + free(program); + return 0; +} + +size_t copy_cache(uint16_t * cache + , uint16_t offset + , size_t cache_size + , void * cache_function_data) +{ + size_t i; + for(i = 0; i < cache_size; i++) + { + printf("\tCP [%zd]->[%zd]: %x\n", i + offset, i, ((uint16_t *) cache_function_data)[i + offset]); + cache[i] = ((uint16_t *) cache_function_data)[i + offset]; + } + return i; +} + From 7ecf1d50368d6abfcdf3de033361a1442268d3de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kn=C3=BCttel?= Date: Wed, 3 Oct 2018 23:26:27 +0200 Subject: [PATCH 08/14] fixed interpreter --- interpreter/interpreter.c | 96 +++++++++++++++++++++++++++++---------- interpreter/interpreter.h | 44 +++++++++++++++--- 2 files changed, 109 insertions(+), 31 deletions(-) diff --git a/interpreter/interpreter.c b/interpreter/interpreter.c index 5b87998..c628bc9 100644 --- a/interpreter/interpreter.c +++ b/interpreter/interpreter.c @@ -1,17 +1,21 @@ #include +#include #include "interpreter.h" machine_state_t machine_state_t_new( void * cache_function_data + , size_t program_size , size_t cache_size + , size_t memory_size , size_t (* cache_block)(uint16_t * cache , uint16_t offset , size_t cache_size , void * cache_function_data) , dispatch_tree_t method_dispatcher) { + machine_state_t state = malloc(sizeof(struct machine_state_s)); if(!state) { @@ -23,11 +27,21 @@ machine_state_t machine_state_t_new( void * cache_function_data free(state); return NULL; } + uint16_t * memory = calloc(sizeof(uint16_t), memory_size); + if(!memory) + { + free(state); + free(cache); + return NULL; + } + + state->program_size = program_size; state->cache = cache; state->cache_block = cache_block; state->cache_size = cache_size; state->cache_loaded = 0; + state->cache_offset = 0; state->cache_function_data = cache_function_data; state->program_counter = 0; @@ -40,6 +54,9 @@ machine_state_t machine_state_t_new( void * cache_function_data } state->stack = NULL; + state->memory = memory; + state->memory_size = memory_size; + state->method_dispatcher = method_dispatcher; return state; @@ -48,15 +65,17 @@ machine_state_t machine_state_t_new( void * cache_function_data void machine_state_t_del(machine_state_t state) { free(state->cache); + free(state->memory); dispatch_tree_t_del(state->method_dispatcher); + bci_stack_t_del(&(state->stack)); free(state); } -char update_cache(machine_state_t state) +char update_cache(machine_state_t state, uint16_t offset) { // Calculate a clever offset for caching. - uint16_t cache_offset = state->program_counter; + uint16_t cache_offset = offset; if((cache_offset + state->cache_size) > state->program_size) { @@ -78,61 +97,64 @@ char update_cache(machine_state_t state) { return 1; } + state->cache_offset = cache_offset; + state->cache_loaded = 1; return 0; } -char machine_state_t_exec_cycle(machine_state_t state) +char machine_state_t_get_word(machine_state_t state, uint16_t offset, uint16_t * result) { - uint16_t opcode, arg; // This would be bad. - if(state->program_counter >= state->program_size) + if(offset >= state->program_size) { return 0b01000000 | 1; } - // Calculate the in-cache offset of the program counter. - int32_t offset = state->program_counter - state->cache_offset; + // Calculate the in-cache offset of the desired offset. + int32_t in_cache_offset = offset - state->cache_offset; // Check if we need to update the cache. - if( offset < 0 + if( in_cache_offset < 0 || !(state->cache_loaded) - // Note: - // +1 for cache starting with 0 - // +1 for the argument - || (offset + 2) > state->cache_size) + ) { - if(update_cache(state)) + if(update_cache(state, offset)) { + state->error = 0b01000000 | 2; return 0b01000000 | 2; } // Re-calculate the in-cache offset - offset = state->program_counter - state->cache_offset; + in_cache_offset = offset - state->cache_offset; } - // Check if the argument is cached. - if(offset + 2 > state->cache_size) + *result = state->cache[in_cache_offset]; + return 0; + +} + +char machine_state_t_exec_cycle(machine_state_t state) +{ + char res = 0; + uint16_t opcode; + res = machine_state_t_get_word(state, state->program_counter, &opcode); + + if(res) { - // Because we have cached the program memory above - // there is no way that we can include the argument - // now. There is something wrong. - return 0b01000000 | 3; + return res; } - opcode = state->cache[offset]; - arg = state->cache[offset + 1]; - bci_core_method_t method = dispatch_tree_t_dispatch( state->method_dispatcher , opcode & BCI_CORE_OPCODE_MASK); if(!method) { + state->error = res; return 0b10000000 | 1; } return BCI_CORE_RESULT_APPLICATION_BITS - & method(arg - , opcode & BCI_CORE_SMALL_ARG_MASK + & method( opcode & BCI_CORE_SMALL_ARG_MASK , state); } @@ -143,3 +165,27 @@ char machine_state_t_default_afterexec(machine_state_t state, uint8_t argc) state->program_counter += 1 + argc; return 0; } + + +char machine_state_t_get_mem(machine_state_t state, uint16_t offset, uint16_t * result) +{ + if(offset > state->memory_size) + { + state->error = 0b01000000 | 15; + return 0b01000000 | 15; + } + + *result = state->memory[offset]; + return 0; +} +char machine_state_t_set_mem(machine_state_t state, uint16_t offset, uint16_t data) +{ + if(offset > state->memory_size) + { + state->error = 0b01000000 | 15; + return 0b01000000 | 15; + } + + state->memory[offset] = data; + return 0; +} diff --git a/interpreter/interpreter.h b/interpreter/interpreter.h index b9213ed..aab2a30 100644 --- a/interpreter/interpreter.h +++ b/interpreter/interpreter.h @@ -2,11 +2,11 @@ #define bci_interpreter_h__ #include -#include "base.h" -#include "method_dispatcher.h" -#include "stack.h" +#include "../base.h" +#include "../method_dispatcher/method_dispatcher.h" +#include "../stack.h" -typedef machine_state_s +typedef struct machine_state_s { // The size of the program in 16-bit words uint16_t program_size; @@ -29,13 +29,32 @@ typedef machine_state_s uint16_t data_reg[BCI_CORE_NUM_REG]; bci_stack_t stack; + size_t memory_size; + uint16_t * memory; + dispatch_tree_t method_dispatcher; + // Possible Error Codes: + // 0b01xxxxxx: memory related internal error + // 0b10xxxxxx: core method related internal error + // 0b00xxxxxx: application related internal error + // + // + // 0b01000000 | 1: Program offset out of bounds + // 0b01000000 | 2: Failed to cache new data + // 0b01000000 | 15: Memory offset out of bounds + // + // + // 0b10000000 | 1: Unknown opcode + char error; + } * machine_state_t; machine_state_t machine_state_t_new( void * cache_function_data + , size_t program_size , size_t cache_size + , size_t memory_size , size_t (* cache_block)(uint16_t * cache , uint16_t offset , size_t cache_size @@ -57,9 +76,8 @@ void machine_state_t_del(machine_state_t state); * - 0b01XXXXXX * Error in the internal memory management (i.e. program counter out * of bounds) - * - 0b01000000 | 1: program_counter > program_size + * - 0b01000000 | 1: program_counter or argument offset > program_size * - 0b01000000 | 2: failed to cache new data - * - 0b01000000 | 3: argument is out of program bounds * * - 0b10XXXXXX * Error while dispatching the method @@ -76,4 +94,18 @@ char machine_state_t_exec_cycle(machine_state_t state); * */ char machine_state_t_default_afterexec(machine_state_t state, uint8_t argc); +/* + * Get the word at offset in the program memory. + * Returns 0 on success, a non-zero value otherwise. + * + * It will set state->error appropiately. + * */ +char machine_state_t_get_word(machine_state_t state, uint16_t offset, uint16_t * result); + +/* + * Get the word at offset in the RAM-alike memory. + * Works like machine_state_t_get_word. + * */ +char machine_state_t_get_mem(machine_state_t state, uint16_t offset, uint16_t * result); +char machine_state_t_set_mem(machine_state_t state, uint16_t offset, uint16_t data); #endif From a3583fa3ba55bf80ac852f859d038b216908d51a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kn=C3=BCttel?= Date: Tue, 9 Oct 2018 11:43:00 +0200 Subject: [PATCH 09/14] changed behaviour of some core methods --- interpreter/core_methods.c | 76 ++++++++++++++++++++------------------ interpreter/core_methods.h | 16 +++++--- 2 files changed, 51 insertions(+), 41 deletions(-) diff --git a/interpreter/core_methods.c b/interpreter/core_methods.c index b63a863..448fc77 100644 --- a/interpreter/core_methods.c +++ b/interpreter/core_methods.c @@ -20,7 +20,7 @@ char bci_cm_ldi(uint8_t small_arg, machine_state_t state) return machine_state_t_default_afterexec(state, 1); } -// @1 -> $0 +// @($1) -> $0 char bci_cm_ld(uint8_t small_arg, machine_state_t state) { BCI_CORE_REGISTER_CHECK(small_arg); @@ -33,6 +33,9 @@ char bci_cm_ld(uint8_t small_arg, machine_state_t state) return res; } + BCI_CORE_REGISTER_CHECK(arg); + arg = state->data_reg[arg]; + res = machine_state_t_get_mem(state, arg, &arg); if(res) { @@ -43,7 +46,7 @@ char bci_cm_ld(uint8_t small_arg, machine_state_t state) return machine_state_t_default_afterexec(state, 1); } -// $0 -> @1 +// $0 -> @($1) char bci_cm_st(uint8_t small_arg, machine_state_t state) { BCI_CORE_REGISTER_CHECK(small_arg); @@ -56,6 +59,9 @@ char bci_cm_st(uint8_t small_arg, machine_state_t state) return res; } + BCI_CORE_REGISTER_CHECK(arg); + arg = state->data_reg[arg]; + res = machine_state_t_set_mem(state, arg, state->data_reg[small_arg]); if(res) { @@ -250,54 +256,43 @@ char bci_cm_eq(uint8_t small_arg, machine_state_t state) return machine_state_t_default_afterexec(state, 0); } -// #1 -> $pc; 0 -> $st_reg +// $0 -> $pc; 0 -> $st_reg char bci_cm_jmp(uint8_t small_arg, machine_state_t state) { - uint16_t arg; - char res = machine_state_t_get_word(state, state->program_counter + 1, &arg); - - if(res) - { - return res; - } + BCI_CORE_REGISTER_CHECK(small_arg) + uint16_t arg = state->data_reg[arg]; + state->status_reg = 0; state->program_counter = arg; return 0; } -// if($st_reg): #1 -> $pc; 0 -> $st_reg +// if($st_reg): $0 -> $pc; 0 -> $st_reg // else: do nothing char bci_cm_cjmp(uint8_t small_arg, machine_state_t state) { uint16_t arg; - char res = machine_state_t_get_word(state, state->program_counter + 1, &arg); - - if(res) - { - return res; - } + BCI_CORE_REGISTER_CHECK(small_arg) + arg = state->data_reg[arg]; if(state->status_reg) { state->program_counter = arg; return 0; } + state->status_reg = 0; - return machine_state_t_default_afterexec(state, 1); + return machine_state_t_default_afterexec(state, 0); } // $pc -> @stack -// #1 -> $pc +// $0 -> $pc char bci_cm_call(uint8_t small_arg, machine_state_t state) { uint16_t arg; - char res = machine_state_t_get_word(state, state->program_counter + 1, &arg); + BCI_CORE_REGISTER_CHECK(small_arg) + arg = state->data_reg[arg]; - if(res) - { - return res; - } - - res = bci_stack_t_push(&(state->stack), state->program_counter); + char res = bci_stack_t_push(&(state->stack), state->program_counter); if(res) { return res; @@ -305,17 +300,13 @@ char bci_cm_call(uint8_t small_arg, machine_state_t state) state->program_counter = arg; return 0; } -// if($st_reg): $pc -> @stack; #1 -> $pc; 0 -> $st_reg +// if($st_reg): $pc -> @stack; $0 -> $pc; 0 -> $st_reg // else: do nothing char bci_cm_ccall(uint8_t small_arg, machine_state_t state) { uint16_t arg; - char res = machine_state_t_get_word(state, state->program_counter + 1, &arg); - - if(res) - { - return res; - } + BCI_CORE_REGISTER_CHECK(small_arg); + arg = state->data_reg[small_arg]; if(state->status_reg) { @@ -328,7 +319,8 @@ char bci_cm_ccall(uint8_t small_arg, machine_state_t state) return 0; } - return machine_state_t_default_afterexec(state, 1); + state->status_reg = 0; + return machine_state_t_default_afterexec(state, 0); } // @stack -> $pc char bci_cm_ret(uint8_t small_arg, machine_state_t state) @@ -354,7 +346,21 @@ char bci_cm_cl(uint8_t small_arg, machine_state_t state) // 1 -> $su_reg char bci_cm_stop(uint8_t small_arg, machine_state_t state) { - state->shutdown_reg = 0; + state->shutdown_reg = 1; return machine_state_t_default_afterexec(state, 0); } +// if($st_reg): 0 -> $st_reg +// else: 1 -> $st_reg +char bci_cm_not(uint8_t small_arg, machine_state_t state) +{ + if(state->status_reg) + { + state->status_reg = 0; + } + else + { + status->status_reg = 1; + } + return machine_state_t_default_afterexec(state, 0); +} diff --git a/interpreter/core_methods.h b/interpreter/core_methods.h index b7fdd08..e36892a 100644 --- a/interpreter/core_methods.h +++ b/interpreter/core_methods.h @@ -32,10 +32,10 @@ // #1 -> $0 char bci_cm_ldi(uint8_t small_arg, machine_state_t state); -// @1 -> $0 +// @($1) -> $0 char bci_cm_ld(uint8_t small_arg, machine_state_t state); -// $0 -> @1 +// $0 -> @($1) char bci_cm_st(uint8_t small_arg, machine_state_t state); @@ -82,18 +82,22 @@ char bci_cm_le(uint8_t small_arg, machine_state_t state); // else: 0 -> $st_reg char bci_cm_eq(uint8_t small_arg, machine_state_t state); -// #1 -> $pc +// if($st_reg): 0 -> $st_reg +// else: 1 -> $st_reg +char bci_cm_not(uint8_t small_arg, machine_state_t state); + +// $1 -> $pc char bci_cm_jmp(uint8_t small_arg, machine_state_t state); -// if($st_reg): #1 -> $pc +// if($st_reg): $1 -> $pc // else: do nothing char bci_cm_cjmp(uint8_t small_arg, machine_state_t state); // $pc -> @stack -// #1 -> $pc +// $0 -> $pc char bci_cm_call(uint8_t small_arg, machine_state_t state); -// if($st_reg): $pc -> @stack; #1 -> $pc +// if($st_reg): $pc -> @stack; $0 -> $pc // else: do nothing char bci_cm_ccall(uint8_t small_arg, machine_state_t state); From 9b599b4ebbc6ed055b63dd764c28182873275444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kn=C3=BCttel?= Date: Sat, 27 Oct 2018 12:14:30 +0200 Subject: [PATCH 10/14] fixed some typos in the core_methods --- interpreter/core_methods.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/interpreter/core_methods.c b/interpreter/core_methods.c index 448fc77..89f169c 100644 --- a/interpreter/core_methods.c +++ b/interpreter/core_methods.c @@ -259,7 +259,7 @@ char bci_cm_eq(uint8_t small_arg, machine_state_t state) // $0 -> $pc; 0 -> $st_reg char bci_cm_jmp(uint8_t small_arg, machine_state_t state) { - BCI_CORE_REGISTER_CHECK(small_arg) + BCI_CORE_REGISTER_CHECK(small_arg); uint16_t arg = state->data_reg[arg]; state->status_reg = 0; @@ -272,7 +272,7 @@ char bci_cm_jmp(uint8_t small_arg, machine_state_t state) char bci_cm_cjmp(uint8_t small_arg, machine_state_t state) { uint16_t arg; - BCI_CORE_REGISTER_CHECK(small_arg) + BCI_CORE_REGISTER_CHECK(small_arg); arg = state->data_reg[arg]; if(state->status_reg) @@ -289,7 +289,7 @@ char bci_cm_cjmp(uint8_t small_arg, machine_state_t state) char bci_cm_call(uint8_t small_arg, machine_state_t state) { uint16_t arg; - BCI_CORE_REGISTER_CHECK(small_arg) + BCI_CORE_REGISTER_CHECK(small_arg); arg = state->data_reg[arg]; char res = bci_stack_t_push(&(state->stack), state->program_counter); @@ -305,6 +305,7 @@ char bci_cm_call(uint8_t small_arg, machine_state_t state) char bci_cm_ccall(uint8_t small_arg, machine_state_t state) { uint16_t arg; + char res; BCI_CORE_REGISTER_CHECK(small_arg); arg = state->data_reg[small_arg]; @@ -360,7 +361,7 @@ char bci_cm_not(uint8_t small_arg, machine_state_t state) } else { - status->status_reg = 1; + state->status_reg = 1; } return machine_state_t_default_afterexec(state, 0); } From 5dc1f88247fac0008c902dddd33adfa51380ec09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kn=C3=BCttel?= Date: Sat, 27 Oct 2018 12:14:57 +0200 Subject: [PATCH 11/14] improved testing and added general Makefile --- Makefile | 16 ++++++++++++++++ interpreter/test/test_interpreter.c | 5 +++++ test/test_stack.c | 7 ++++++- 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..89e3480 --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +CC=gcc +objects= stack.o method_dispatcher/method_dispatcher.o interpreter/core_methods.o interpreter/interpreter.o + +all: $(objects) test + +CFLAG= -c -O -o + +%.o: %.c + $(CC) $(CFLAG) $@ $< + +.PHONY: test + +test: + cd test && make + cd method_dispatcher/test && make + cd interpreter/test && make diff --git a/interpreter/test/test_interpreter.c b/interpreter/test/test_interpreter.c index 5793f0c..62db833 100644 --- a/interpreter/test/test_interpreter.c +++ b/interpreter/test/test_interpreter.c @@ -1,5 +1,6 @@ #include #include +#include #include "../interpreter.h" #include "../core_methods.h" #include "../../method_dispatcher/method_dispatcher.h" @@ -39,9 +40,13 @@ int main(void) machine_state_t_exec_cycle(state); machine_state_t_exec_cycle(state); printf("data_reg[0]: %x\n", state->data_reg[0]); + assert(state->data_reg[0] == 0xfefe); printf("data_reg[1]: %x\n", state->data_reg[1]); + assert(state->data_reg[1] == 5); printf("data_reg[2]: %x\n", state->data_reg[2]); + assert(state->data_reg[2] == 3); printf("program_counter: %d\n", state->program_counter); + assert(state->program_counter == 8); dispatch_tree_autoinserter_t_del(inserter); machine_state_t_del(state); free(program); diff --git a/test/test_stack.c b/test/test_stack.c index 05fecc1..328c35c 100644 --- a/test/test_stack.c +++ b/test/test_stack.c @@ -1,5 +1,6 @@ #include #include "../stack.h" +#include int main(void) { @@ -13,10 +14,14 @@ int main(void) { bci_stack_t_push(&stack, (uint16_t) i); } + --i; while(!status) { status = bci_stack_t_pop(&stack, &res); - printf("%d\n", res); + if(!status) + { + assert(res == i--); + } } From 84ca38924ecb3ab4c571eedc456959639d38891e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kn=C3=BCttel?= Date: Sat, 27 Oct 2018 16:52:13 +0200 Subject: [PATCH 12/14] added Makefile for the interpreter --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 89e3480..07d3c87 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ objects= stack.o method_dispatcher/method_dispatcher.o interpreter/core_methods. all: $(objects) test -CFLAG= -c -O -o +CFLAG= -c -DDEBUG -O -o %.o: %.c $(CC) $(CFLAG) $@ $< From d472a14f59cbc3f3bebecd2dacb8ca9b29d87b1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kn=C3=BCttel?= Date: Sat, 27 Oct 2018 16:53:40 +0200 Subject: [PATCH 13/14] added machine_state_t_exec and fixed some bugs --- interpreter/core_methods.c | 7 +++++-- interpreter/interpreter.c | 28 +++++++++++++++++++++++++++- interpreter/interpreter.h | 10 ++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/interpreter/core_methods.c b/interpreter/core_methods.c index 89f169c..b7c26a2 100644 --- a/interpreter/core_methods.c +++ b/interpreter/core_methods.c @@ -271,16 +271,19 @@ char bci_cm_jmp(uint8_t small_arg, machine_state_t state) // else: do nothing char bci_cm_cjmp(uint8_t small_arg, machine_state_t state) { - uint16_t arg; + uint16_t arg = small_arg; BCI_CORE_REGISTER_CHECK(small_arg); +#ifdef DEBUG + printf("MSG: cjmp: arg=0x%x (=0x%x)\n", arg, state->data_reg[arg]); +#endif arg = state->data_reg[arg]; if(state->status_reg) { state->program_counter = arg; + state->status_reg = 0; return 0; } - state->status_reg = 0; return machine_state_t_default_afterexec(state, 0); } diff --git a/interpreter/interpreter.c b/interpreter/interpreter.c index c628bc9..4089fdd 100644 --- a/interpreter/interpreter.c +++ b/interpreter/interpreter.c @@ -50,7 +50,7 @@ machine_state_t machine_state_t_new( void * cache_function_data int i; for(i = 0; i < BCI_CORE_NUM_REG; i++) { - state->data_reg[BCI_CORE_NUM_REG] = 0; + state->data_reg[i] = 0; } state->stack = NULL; @@ -95,6 +95,9 @@ char update_cache(machine_state_t state, uint16_t offset) if(cached != state->cache_size) { + #ifdef DEBUG + printf("ERROR: should have cached %zu words, but got %zu.\n", state->cache_size, cached); + #endif return 1; } state->cache_offset = cache_offset; @@ -121,6 +124,9 @@ char machine_state_t_get_word(machine_state_t state, uint16_t offset, uint16_t * { if(update_cache(state, offset)) { + #ifdef DEBUG + printf("ERROR: failed to update cache\n"); + #endif state->error = 0b01000000 | 2; return 0b01000000 | 2; } @@ -144,6 +150,12 @@ char machine_state_t_exec_cycle(machine_state_t state) return res; } +#ifdef DEBUG + printf("MSG: opcode = 0x%x, small_arg = 0x%x\n" + , opcode & BCI_CORE_OPCODE_MASK + , opcode & BCI_CORE_SMALL_ARG_MASK); +#endif + bci_core_method_t method = dispatch_tree_t_dispatch( state->method_dispatcher , opcode & BCI_CORE_OPCODE_MASK); @@ -189,3 +201,17 @@ char machine_state_t_set_mem(machine_state_t state, uint16_t offset, uint16_t da state->memory[offset] = data; return 0; } + + + + +char machine_state_t_exec(machine_state_t state) +{ + char status = 0; + while((!status) && (!state->shutdown_reg)) + { + status = machine_state_t_exec_cycle(state); + } + state->error = status; + return status; +} diff --git a/interpreter/interpreter.h b/interpreter/interpreter.h index aab2a30..4829148 100644 --- a/interpreter/interpreter.h +++ b/interpreter/interpreter.h @@ -88,6 +88,16 @@ void machine_state_t_del(machine_state_t state); * */ char machine_state_t_exec_cycle(machine_state_t state); + +/* + * Runs ``machine_state_t_exec_cycle`` until either this function + * returns a non-zero value or a non-zero value is stored in + * ``state->shutdown_reg``. + * Sets ``state->error`` to the last return value of ``machine_state_t_exec_cycle`` + * and returns it. + * */ +char machine_state_t_exec(machine_state_t state); + /* * Do the default updates on the machine state. * This will be basically increasing the program counter. From 24ae0d00db2297edc857086beec5e9c019d61e92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kn=C3=BCttel?= Date: Sat, 27 Oct 2018 17:19:52 +0200 Subject: [PATCH 14/14] disabled debug mode and added clean target --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 07d3c87..73f7ffb 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ objects= stack.o method_dispatcher/method_dispatcher.o interpreter/core_methods. all: $(objects) test -CFLAG= -c -DDEBUG -O -o +CFLAG= -c -O -o %.o: %.c $(CC) $(CFLAG) $@ $< @@ -14,3 +14,6 @@ test: cd test && make cd method_dispatcher/test && make cd interpreter/test && make + +clean: + - rm $(objects)