diff --git a/vvm/Makefile b/Makefile similarity index 100% rename from vvm/Makefile rename to Makefile diff --git a/README.md b/README.md index ecd7856..6f35541 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,105 @@ -Virtual Machines ----------------- +Veits Virtual Machine +--------------------- -[![Build Status](https://travis-ci.org/hellerve/Virtual-Machines.png?branch=master)](https://travis-ci.org/hellerve/Virtual-Machines) +A virtual machine that executes assembler-like code. + +Performance +----------- + +Performance is pretty okay on basic, small programs. The included factorial +function takes 0.1 second on 100000 iterations. As a scale, a Python 3.3 program +on the same machine using the code: + +`` +def fac(n): + if n < 2: return 1 + else: return n * fac(n-1) +fac(12) +`` + +takes about 3.7 seconds on 100000 iterations. + +This does not say anything about overall performance though and I am not +sure whether this small, funny test has any real value in measuring performance. +Also, Python is much more feature-rich, so you cannot compare the two at all. + +DISCLAIMER: Parsing takes quite a long time, so try to write your programs as +concise as possible. + +Instruction set +--------------- + +Up until now, all the operations are executed on integers(hence the +I\* prefix). + +*Operations overview*: + +* IADD - Adds the two items to each other that are on top of the stack +and stores the result on top of the stack. + +* ISUB - Subtracts the two items from each other that are on top of the +stack and stores the result on top of the stack. + +* IMULT - Multiplies the two items to each other that are on top of the +stack and stores the result on top of the stack. + +* IDIV - Performs a division operation to the two items that are on top +of the stack and stores the result on top of the stack. + +* IMOD - Performs a modulo operation to the two items that are on top +of the stack and stores the result on top of the stack. + +* ILT - Checks whether the item on top of the stack is greater than the +item below it and stores a boolean on top of the stack. + +* IEQ - Checks whether the item on top of the stack is equal to the +item below it and stores a boolean on top of the stack. + +* IGT - Checks whether the item on top of the stack is smaller than the +item below it and stores a boolean on top of the stack. + +* ILEQ - Checks whether the item on top of the stack is smaller than or +equal to the item below it and stores a boolean on top of the stack. + +* IGEQ - Checks whether the item on top of the stack is greater than or +equal to the item below it and stores a boolean on top of the stack. + +* BR - Jumps to the instruction that is provided as an argument. + +* BRT - Jumps to the instruction that is provided as an argument if the +value on top of the stack is TRUE. + +* BRF - Jumps to the instruction that is provided as an argument if the +value on top of the stack is FALSE. + +* ICONST - Puts the argument provided to the operation on top of the +stack. + +* LOAD - Loads an element from any position on the stack on top of the +stack(usually used to get function arguments like this: LOAD -3). + +* GLOAD - Loads an element from any position on the data segment on +top of the stack. + +* STORE - Stores an element on the stack. + +* GSTORE - Stores an element in the data segment. + +* PRINT - Prints the element on top of the stack as character. + +* IPRINT - Prints the element on top of the stack as integer. + +* POP - Pops the element on top of the stack. + +* HALT - Ends the program. + +* CALL - calls a subroutine with a number of arguments. + +* RET - Returns from a subroutine with a return value. + +* FETCH - Fetches a value. + +* IINC -Increments the value on top of the stack by one(equal to ++). + +* IDEC -Decrements the value on top of the stack by one(equal to --). -Just a bunch of immature interpreters. One interprets brainfuck code(nbfi - -naive brainfuck interpreter), the other uses an assembly-based dsl. diff --git a/nbfi/Makefile b/nbfi/Makefile deleted file mode 100644 index 3e43751..0000000 --- a/nbfi/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -override CFLAGS+=-Werror -Wall -g -fPIC -O2 -DNDEBUG -std=c99 -ftrapv -Wfloat-equal -Wundef -Wwrite-strings -Wconversion -Wuninitialized -pedantic -PREFIX=/usr/bin/ -BUILDDIR=bin/ - -TARGET=nbfi -SOURCES=$(wildcard src/*.c) - -#Makes everything -all: - mkdir $(BUILDDIR) 2> /dev/null || true - cc $(CFLAGS) $(SOURCES) -o $(BUILDDIR)$(TARGET) - @echo - @echo Running tests: - @echo - make tests - @echo Compilation successfull. - -# Runs the tests -tests: - ./test.sh - -#Uses picky extensions and makes everything(Extensions may break compiling) -dev: - make all CFLAGS+=-Wshadow -Wunreachable-code -Wswitch-enum -Wswitch-default -Wcast-align -Winit-self -Wpointer-arith - -#Cleans directory(no uninstall!) -clean: - rm -rf bin - -#Installs into specified(or default) directory -install: - install -d $(PREFIX)$(TARGET) - install $(BUILDDIR)$(TARGET) $(PREFIX)$(TARGET) - -#Uninstalls from specified(or default)directory -uninstall: - rm -rf $(PREFIX)$(TARGET) - -#Checks for bad functions -BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)' -check: - @echo Files with potentially dangerous functions: - @grep $(BADFUNCS) $(SOURCES) || echo None diff --git a/nbfi/README.md b/nbfi/README.md deleted file mode 100644 index fd04bac..0000000 --- a/nbfi/README.md +++ /dev/null @@ -1,4 +0,0 @@ -Naive Brainf\*ck Interpreter ---------------------------- - -A virtual machine that executes brainf\*ck code. diff --git a/nbfi/src/nbfi.c b/nbfi/src/nbfi.c deleted file mode 100644 index 9cde034..0000000 --- a/nbfi/src/nbfi.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include - -/*end instruction*/ -#define END 0 -/*increment pointer instruction, equivalent to > */ -#define INC_DP 1 -/*decrement pointer instruction, equivalent to < */ -#define DEC_DP 2 -/*increment value instruction, equivalent to + */ -#define INC_VAL 3 -/*decrement value instruction, equivalent to - */ -#define DEC_VAL 4 -/*output value instruction, equivalent to . */ -#define OUT 5 -/*input value instruction, equivalent to , */ -#define IN 6 -/*jump forward instruction, equivalent to [ */ -#define JMP_FWD 7 -/*jump back instruction, equivalent to ] */ -#define JMP_BCK 8 - -/*Maximum program size*/ -#define PROGRAM_SIZE 1048576 -/*Maximum stack size*/ -#define MAX_SIZE 5024291 -/*Maximum data size*/ -#define DATA_SIZE 1638375 - -/*Push macro, implements stack operation push*/ -#define PUSH(A) (stack[sp++] = A) -/*Pop macro, implements stack operation pop*/ -#define POP() (stack[--sp]) -/*Empty macro, implements stack operation check if empty*/ -#define EMPTY() (sp == 0) -/*Full macro, implements stack operation check if full*/ -#define FULL() (sp == MAX_SIZE) - - -/** - * @brief die - * @param code -> the error code - * @param message -> the error message - * - * Lets the program die and emits an error message. - */ -static inline void die(int code, const char* message){ - fprintf(stderr, "%s\n", message); - exit(code); -} - -/** - * @brief An instruction struct - * - * Consists of operator and operand, - * the easiest way of abstracting - * an instruction. - */ -struct instruction{ - unsigned int operator; ///< Operator - unsigned int operand; ///< Operand -}; - -/*The program as an array of structs*/ -static struct instruction program[PROGRAM_SIZE]; -/*The stack*/ -static unsigned int stack[MAX_SIZE]; -/*The stack pointer*/ -static unsigned long sp = 0; - -/** - * @brief compile - * @param fp -> the file - * - * Compiles a file to bytecode and saves that within program. - */ -void compile(FILE* fp){ - unsigned int pc = 0, jmp_pc; - int ip; - while ((ip = getc(fp)) != EOF && pc < MAX_SIZE){ - switch (ip) { - case '>': program[pc].operator = INC_DP; break; - case '<': program[pc].operator = DEC_DP; break; - case '+': program[pc].operator = INC_VAL; break; - case '-': program[pc].operator = DEC_VAL; break; - case '.': program[pc].operator = OUT; break; - case ',': program[pc].operator = IN; break; - case '[': - program[pc].operator = JMP_FWD; - if (FULL()) - die(127, "nbfi:compile: Cannot jump forwards: Stack is full."); - PUSH(pc); - break; - case ']': - if (EMPTY()) - die(127, "nbfi:compile: Cannot jump backwards: Stack is full."); - jmp_pc = POP(); - program[pc].operator = JMP_BCK; - program[pc].operand = jmp_pc; - program[jmp_pc].operand = pc; - break; - default: - if(ip > 32 && ip < 128) - fprintf(stderr, "nbfi:compile: Warning: Unknown command: %c\n", ip); - pc--; - break; - } - pc++; - } - if(!EMPTY()) - die(127, "nbfi:compile: Program ends with non-empty stack."); - if(pc == MAX_SIZE) - die(127, "nbfi:compile: Program exceeds maximum program size."); - program[pc].operator = END; -} - -/** - * @brief execute - * - * Executes the bytecode within program. - */ -void execute(){ - unsigned int data[DATA_SIZE], pc = 0; - unsigned int ptr = DATA_SIZE; - while (--ptr) data[ptr] = 0; - while (program[pc].operator != END && ptr < DATA_SIZE){ - switch (program[pc].operator){ - case INC_DP: ptr++; break; - case DEC_DP: ptr--; break; - case INC_VAL: data[ptr]++; break; - case DEC_VAL: data[ptr]--; break; - case OUT: putchar((signed int)data[ptr]); break; - case IN: data[ptr] = (unsigned int)getchar(); break; - case JMP_FWD: if(!data[ptr]) { pc = program[pc].operand; } break; - case JMP_BCK: if(data[ptr]) { pc = program[pc].operand; } break; - default: die(127, "nbfi:execute: Unknown instruction."); - } - pc++; - } - if(ptr == DATA_SIZE) - die(127, "nbfi:execute: Program used up too much memory."); -} - -/* - * @brief main - * @param argc -> argument counter - * @param argv -> argument vector - * - * compiles and executes brainfuck code from a file. - */ -int main(int argc, const char * argv[]){ - FILE *fp; - if(argc != 2) - die(127, "nbfi:parse: Wrong number of arguments supplied."); - if(!(fp = fopen(argv[1], "r"))) - die(127, "nbfi:parse: File could not be opened."); - compile(fp); - fclose(fp); - execute(); - return 0; -} diff --git a/nbfi/test.sh b/nbfi/test.sh deleted file mode 100755 index b88e43f..0000000 --- a/nbfi/test.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -for i in `ls test | grep -v fail` ; do - echo Running test $i: - echo --------------------- - bin/nbfi test/$i - return=$? - if [ $return != 0 ] ; then - echo Test $i failed. - exit 1 - fi - echo - echo --------------------- - echo End of test $i - echo -done - -for i in `ls test/*fail*` ; do - echo Running expected fail test $i: - echo --------------------- - bin/nbfi $i - return=$? - if [ $return != 127 ] ; then - echo Test $i failed. - exit 1 - fi - echo - echo --------------------- - echo End of test $i - echo -done diff --git a/nbfi/test/helloworld.bf b/nbfi/test/helloworld.bf deleted file mode 100644 index f079b46..0000000 --- a/nbfi/test/helloworld.bf +++ /dev/null @@ -1,42 +0,0 @@ -++++++++++ -[ - > - +++++++ - > - ++++++++++ - > - +++ - > - + - <<<< - - -] -> -++ -. -> -+ -. -+++++++ -.. -+++ -. -> -++ -. -<< -+++++++++++++++ -. -> -. -+++ -. ------- -. --------- -. -> -+ -. -> -. diff --git a/nbfi/test/hw.bf b/nbfi/test/hw.bf deleted file mode 100644 index 265e751..0000000 --- a/nbfi/test/hw.bf +++ /dev/null @@ -1 +0,0 @@ -++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. diff --git a/nbfi/test/parse_fail b/nbfi/test/parse_fail deleted file mode 100644 index 558ed37..0000000 --- a/nbfi/test/parse_fail +++ /dev/null @@ -1 +0,0 @@ -[ diff --git a/nbfi/test/square.bf b/nbfi/test/square.bf deleted file mode 100644 index 46550a3..0000000 --- a/nbfi/test/square.bf +++ /dev/null @@ -1,5 +0,0 @@ -++++[>+++++<-]>[<++++++++++++>-]+<+[ ->[>+>+<<-]++>>[<<+>>-]>>>[-]++>[-]+ ->>>+[[-]++++++>>>]<<<[[<++++++++<++>>-]+<.<[>----<-]<] -<<[>>>>>[>>>[-]+++++++++<[>-<-]+++++++++>[-[<->-]+[<<<]]<[>+<-]>]<<-]<<- -] diff --git a/vvm/src/main.c b/src/main.c similarity index 100% rename from vvm/src/main.c rename to src/main.c diff --git a/vvm/src/opcode.c b/src/opcode.c similarity index 100% rename from vvm/src/opcode.c rename to src/opcode.c diff --git a/vvm/src/opcode.h b/src/opcode.h similarity index 100% rename from vvm/src/opcode.h rename to src/opcode.h diff --git a/vvm/src/util.h b/src/util.h similarity index 100% rename from vvm/src/util.h rename to src/util.h diff --git a/vvm/src/vm.c b/src/vm.c similarity index 100% rename from vvm/src/vm.c rename to src/vm.c diff --git a/vvm/src/vm.h b/src/vm.h similarity index 100% rename from vvm/src/vm.h rename to src/vm.h diff --git a/vvm/test.sh b/test.sh similarity index 100% rename from vvm/test.sh rename to test.sh diff --git a/vvm/test/argc_fail b/test/argc_fail similarity index 100% rename from vvm/test/argc_fail rename to test/argc_fail diff --git a/vvm/test/command_fail b/test/command_fail similarity index 100% rename from vvm/test/command_fail rename to test/command_fail diff --git a/vvm/test/factorial b/test/factorial similarity index 100% rename from vvm/test/factorial rename to test/factorial diff --git a/vvm/test/helloworld b/test/helloworld similarity index 100% rename from vvm/test/helloworld rename to test/helloworld diff --git a/vvm/README.md b/vvm/README.md deleted file mode 100644 index 6f35541..0000000 --- a/vvm/README.md +++ /dev/null @@ -1,105 +0,0 @@ -Veits Virtual Machine ---------------------- - -A virtual machine that executes assembler-like code. - -Performance ------------ - -Performance is pretty okay on basic, small programs. The included factorial -function takes 0.1 second on 100000 iterations. As a scale, a Python 3.3 program -on the same machine using the code: - -`` -def fac(n): - if n < 2: return 1 - else: return n * fac(n-1) -fac(12) -`` - -takes about 3.7 seconds on 100000 iterations. - -This does not say anything about overall performance though and I am not -sure whether this small, funny test has any real value in measuring performance. -Also, Python is much more feature-rich, so you cannot compare the two at all. - -DISCLAIMER: Parsing takes quite a long time, so try to write your programs as -concise as possible. - -Instruction set ---------------- - -Up until now, all the operations are executed on integers(hence the -I\* prefix). - -*Operations overview*: - -* IADD - Adds the two items to each other that are on top of the stack -and stores the result on top of the stack. - -* ISUB - Subtracts the two items from each other that are on top of the -stack and stores the result on top of the stack. - -* IMULT - Multiplies the two items to each other that are on top of the -stack and stores the result on top of the stack. - -* IDIV - Performs a division operation to the two items that are on top -of the stack and stores the result on top of the stack. - -* IMOD - Performs a modulo operation to the two items that are on top -of the stack and stores the result on top of the stack. - -* ILT - Checks whether the item on top of the stack is greater than the -item below it and stores a boolean on top of the stack. - -* IEQ - Checks whether the item on top of the stack is equal to the -item below it and stores a boolean on top of the stack. - -* IGT - Checks whether the item on top of the stack is smaller than the -item below it and stores a boolean on top of the stack. - -* ILEQ - Checks whether the item on top of the stack is smaller than or -equal to the item below it and stores a boolean on top of the stack. - -* IGEQ - Checks whether the item on top of the stack is greater than or -equal to the item below it and stores a boolean on top of the stack. - -* BR - Jumps to the instruction that is provided as an argument. - -* BRT - Jumps to the instruction that is provided as an argument if the -value on top of the stack is TRUE. - -* BRF - Jumps to the instruction that is provided as an argument if the -value on top of the stack is FALSE. - -* ICONST - Puts the argument provided to the operation on top of the -stack. - -* LOAD - Loads an element from any position on the stack on top of the -stack(usually used to get function arguments like this: LOAD -3). - -* GLOAD - Loads an element from any position on the data segment on -top of the stack. - -* STORE - Stores an element on the stack. - -* GSTORE - Stores an element in the data segment. - -* PRINT - Prints the element on top of the stack as character. - -* IPRINT - Prints the element on top of the stack as integer. - -* POP - Pops the element on top of the stack. - -* HALT - Ends the program. - -* CALL - calls a subroutine with a number of arguments. - -* RET - Returns from a subroutine with a return value. - -* FETCH - Fetches a value. - -* IINC -Increments the value on top of the stack by one(equal to ++). - -* IDEC -Decrements the value on top of the stack by one(equal to --). -