fixed interpreter
This commit is contained in:
parent
6612918cf7
commit
7ecf1d5036
|
@ -1,17 +1,21 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
machine_state_t machine_state_t_new( void * cache_function_data
|
machine_state_t machine_state_t_new( void * cache_function_data
|
||||||
|
, size_t program_size
|
||||||
, size_t cache_size
|
, size_t cache_size
|
||||||
|
, size_t memory_size
|
||||||
, size_t (* cache_block)(uint16_t * cache
|
, size_t (* cache_block)(uint16_t * cache
|
||||||
, uint16_t offset
|
, uint16_t offset
|
||||||
, size_t cache_size
|
, size_t cache_size
|
||||||
, void * cache_function_data)
|
, void * cache_function_data)
|
||||||
, dispatch_tree_t method_dispatcher)
|
, dispatch_tree_t method_dispatcher)
|
||||||
{
|
{
|
||||||
|
|
||||||
machine_state_t state = malloc(sizeof(struct machine_state_s));
|
machine_state_t state = malloc(sizeof(struct machine_state_s));
|
||||||
if(!state)
|
if(!state)
|
||||||
{
|
{
|
||||||
|
@ -23,11 +27,21 @@ machine_state_t machine_state_t_new( void * cache_function_data
|
||||||
free(state);
|
free(state);
|
||||||
return NULL;
|
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 = cache;
|
||||||
state->cache_block = cache_block;
|
state->cache_block = cache_block;
|
||||||
state->cache_size = cache_size;
|
state->cache_size = cache_size;
|
||||||
state->cache_loaded = 0;
|
state->cache_loaded = 0;
|
||||||
|
state->cache_offset = 0;
|
||||||
state->cache_function_data = cache_function_data;
|
state->cache_function_data = cache_function_data;
|
||||||
|
|
||||||
state->program_counter = 0;
|
state->program_counter = 0;
|
||||||
|
@ -40,6 +54,9 @@ machine_state_t machine_state_t_new( void * cache_function_data
|
||||||
}
|
}
|
||||||
state->stack = NULL;
|
state->stack = NULL;
|
||||||
|
|
||||||
|
state->memory = memory;
|
||||||
|
state->memory_size = memory_size;
|
||||||
|
|
||||||
state->method_dispatcher = method_dispatcher;
|
state->method_dispatcher = method_dispatcher;
|
||||||
|
|
||||||
return state;
|
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)
|
void machine_state_t_del(machine_state_t state)
|
||||||
{
|
{
|
||||||
free(state->cache);
|
free(state->cache);
|
||||||
|
free(state->memory);
|
||||||
dispatch_tree_t_del(state->method_dispatcher);
|
dispatch_tree_t_del(state->method_dispatcher);
|
||||||
|
bci_stack_t_del(&(state->stack));
|
||||||
free(state);
|
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.
|
// Calculate a clever offset for caching.
|
||||||
uint16_t cache_offset = state->program_counter;
|
uint16_t cache_offset = offset;
|
||||||
if((cache_offset + state->cache_size)
|
if((cache_offset + state->cache_size)
|
||||||
> state->program_size)
|
> state->program_size)
|
||||||
{
|
{
|
||||||
|
@ -78,61 +97,64 @@ char update_cache(machine_state_t state)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
state->cache_offset = cache_offset;
|
||||||
|
state->cache_loaded = 1;
|
||||||
return 0;
|
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.
|
// This would be bad.
|
||||||
if(state->program_counter >= state->program_size)
|
if(offset >= state->program_size)
|
||||||
{
|
{
|
||||||
return 0b01000000 | 1;
|
return 0b01000000 | 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the in-cache offset of the program counter.
|
// Calculate the in-cache offset of the desired offset.
|
||||||
int32_t offset = state->program_counter - state->cache_offset;
|
int32_t in_cache_offset = offset - state->cache_offset;
|
||||||
|
|
||||||
// Check if we need to update the cache.
|
// Check if we need to update the cache.
|
||||||
if( offset < 0
|
if( in_cache_offset < 0
|
||||||
|| !(state->cache_loaded)
|
|| !(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;
|
return 0b01000000 | 2;
|
||||||
}
|
}
|
||||||
// Re-calculate the in-cache offset
|
// 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.
|
*result = state->cache[in_cache_offset];
|
||||||
if(offset + 2 > state->cache_size)
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
char machine_state_t_exec_cycle(machine_state_t state)
|
||||||
{
|
{
|
||||||
// Because we have cached the program memory above
|
char res = 0;
|
||||||
// there is no way that we can include the argument
|
uint16_t opcode;
|
||||||
// now. There is something wrong.
|
res = machine_state_t_get_word(state, state->program_counter, &opcode);
|
||||||
return 0b01000000 | 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
opcode = state->cache[offset];
|
if(res)
|
||||||
arg = state->cache[offset + 1];
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
bci_core_method_t method = dispatch_tree_t_dispatch(
|
bci_core_method_t method = dispatch_tree_t_dispatch(
|
||||||
state->method_dispatcher
|
state->method_dispatcher
|
||||||
, opcode & BCI_CORE_OPCODE_MASK);
|
, opcode & BCI_CORE_OPCODE_MASK);
|
||||||
if(!method)
|
if(!method)
|
||||||
{
|
{
|
||||||
|
state->error = res;
|
||||||
return 0b10000000 | 1;
|
return 0b10000000 | 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return BCI_CORE_RESULT_APPLICATION_BITS
|
return BCI_CORE_RESULT_APPLICATION_BITS
|
||||||
& method(arg
|
& method( opcode & BCI_CORE_SMALL_ARG_MASK
|
||||||
, opcode & BCI_CORE_SMALL_ARG_MASK
|
|
||||||
, state);
|
, state);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -143,3 +165,27 @@ char machine_state_t_default_afterexec(machine_state_t state, uint8_t argc)
|
||||||
state->program_counter += 1 + argc;
|
state->program_counter += 1 + argc;
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
#define bci_interpreter_h__
|
#define bci_interpreter_h__
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "base.h"
|
#include "../base.h"
|
||||||
#include "method_dispatcher.h"
|
#include "../method_dispatcher/method_dispatcher.h"
|
||||||
#include "stack.h"
|
#include "../stack.h"
|
||||||
|
|
||||||
typedef machine_state_s
|
typedef struct machine_state_s
|
||||||
{
|
{
|
||||||
// The size of the program in 16-bit words
|
// The size of the program in 16-bit words
|
||||||
uint16_t program_size;
|
uint16_t program_size;
|
||||||
|
@ -29,13 +29,32 @@ typedef machine_state_s
|
||||||
uint16_t data_reg[BCI_CORE_NUM_REG];
|
uint16_t data_reg[BCI_CORE_NUM_REG];
|
||||||
bci_stack_t stack;
|
bci_stack_t stack;
|
||||||
|
|
||||||
|
size_t memory_size;
|
||||||
|
uint16_t * memory;
|
||||||
|
|
||||||
|
|
||||||
dispatch_tree_t method_dispatcher;
|
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 machine_state_t_new( void * cache_function_data
|
machine_state_t machine_state_t_new( void * cache_function_data
|
||||||
|
, size_t program_size
|
||||||
, size_t cache_size
|
, size_t cache_size
|
||||||
|
, size_t memory_size
|
||||||
, size_t (* cache_block)(uint16_t * cache
|
, size_t (* cache_block)(uint16_t * cache
|
||||||
, uint16_t offset
|
, uint16_t offset
|
||||||
, size_t cache_size
|
, size_t cache_size
|
||||||
|
@ -57,9 +76,8 @@ void machine_state_t_del(machine_state_t state);
|
||||||
* - 0b01XXXXXX
|
* - 0b01XXXXXX
|
||||||
* Error in the internal memory management (i.e. program counter out
|
* Error in the internal memory management (i.e. program counter out
|
||||||
* of bounds)
|
* 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 | 2: failed to cache new data
|
||||||
* - 0b01000000 | 3: argument is out of program bounds
|
|
||||||
*
|
*
|
||||||
* - 0b10XXXXXX
|
* - 0b10XXXXXX
|
||||||
* Error while dispatching the method
|
* 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);
|
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
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user