diff --git a/interpreter/interpreter/interpreter.c b/interpreter/interpreter/interpreter.c index 5b87998..c628bc9 100644 --- a/interpreter/interpreter/interpreter.c +++ b/interpreter/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/interpreter.h b/interpreter/interpreter/interpreter.h index b9213ed..aab2a30 100644 --- a/interpreter/interpreter/interpreter.h +++ b/interpreter/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