fixed core methods and added test
This commit is contained in:
parent
dff2691836
commit
bb07a050e6
360
interpreter/interpreter/core_methods.c
Normal file
360
interpreter/interpreter/core_methods.c
Normal file
|
@ -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);
|
||||
}
|
||||
|
110
interpreter/interpreter/core_methods.h
Normal file
110
interpreter/interpreter/core_methods.h
Normal file
|
@ -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
|
14
interpreter/interpreter/test/Makefile
Normal file
14
interpreter/interpreter/test/Makefile
Normal file
|
@ -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:
|
||||
|
64
interpreter/interpreter/test/test_interpreter.c
Normal file
64
interpreter/interpreter/test/test_interpreter.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user