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; +} +