Micro Virtual Machine - A weekend project to build a virtual machine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
4.7 KiB

# uVM - Micro Virtual Machine
7 years ago
uVM is simply an experiment in developing a working virtual machine with it's own bytecode.
## Contributing
I am taking any and all contributions! This is a fun project for me and I'd like to see other people throw
their ideas into this.
## Requirements
* CMake version 3.8 or higher
* Clang and Clang++
* Boost (because im lazy)
## Building
1. `git clone` the repository
2. `cmake .`
3. `make`
7 years ago
## Usage
_NOTE_: This is unimplemented - Looking for contributors
`uvm [-v] [-h] [-d <stack_depth>] -f <your_file_of_bytecode>.uc`
7 years ago
* `-v`: Enable verbose logging mode
* `-h`: Show usage
* `-f <file_name>.uc`: Load the uvm bytecode file for processing
* `-d <stack_depth>`: The maximum stack depth in words
7 years ago
## Testing
CMake tests are used to confirm a handful of sample programs will run successfully in the VM
1. `cmake .`
2. `make test`
## Architecture
uVM is a _stack machine_. That is, it gets all of it's arguments from the stack, and returns the result
of the computation back to the stack when it's done.
7 years ago
There are some exceptions to this. In particular the current version of uvm supports registers.
## uVM Instruction Set
uVM possesses the standard issue instruction set you might expect in a simple VM:
| Instruction | Opcode | Action |
| ------------ | ------ | -------------------------------------------------------------------------------------- |
| ipush _X_ | 0 | Pushes _integer_ X onto the stack |
| isave0 | 1 | Takes the top of the stack and stores it in `t0` |
| isave1 | 2 | Takes the top of the stack and stores it in `t1` |
| isave2 | 3 | Takes the top of the stack and stores it in `t2` |
| iload0 | 4 | Puts the value in `t0` onto the top of the stack |
| iload1 | 5 | Puts the value in `t1` onto the top of the stack |
| iload2 | 6 | Puts the value in `t2` onto the top of the stack |
| icmp | 7 | Compares the top two items on the stack together and returns a boolean result |
| iadd | 8 | Adds the top two _integer_ arguments of the stack together |
| isub | 9 | Subtracts the top two _integer_ arguments of the stack from each other |
| jmp _BYTE_ | A | Unconditional jump to _BYTE_ |
| jc _BYTE_ | B | Jump to _BYTE_ if the top of the stack is a 1 |
| halt | C | Halts the VM |
| print | D | Prints the current top of the stack as an integer |
| imul | E | Multiples the top two integers on the stack |
| call | F | TBD |
| idiv | 10 | Takes the top two values on the stack and performs integer division on them |
| irem | 11 | Takes the integer remainder of the division of the top two integer values on the stack |
Additionally some registers exist to ease computation:
7 years ago
| Register | Use |
| -------- | ---------------------------------- |
| t0 | Temporary _integer_ register 0 |
| t1 | Temporary _integer_ register 1 |
| t2 | Temporary _integer_ register 2 |
| cf | Comparison flag register |
As I learn more about VM development this instruction set will likely become much more robust.
7 years ago
## uVM Calling Convention
uVM borrows heavily from past work - so a CDECL convention modified to
work with stack machines (result is store on the top of the stack instead of
EAX) is used.
7 years ago
## TODO
- [ ] Tests for good paths for all instructions
- [ ] Come up with a clever way to support floating point operations
- [ ] Tests for uncompilable code
- [ ] Tests for maximum stack size reached
- [ ] Tests to make sure the maximum stack depth is always greater than 0
- [ ] Test to make sure that run doesn't run when the byte code array is empty
- [ ] Logging out current stack position, etc when verbose mode is enabled
- [ ] If verbose mode isn't enabled it shows the ascii loading while processing
- [ ] It would be cool to eventually write a high level language compiler that compiles down to the uvm