#+TITLE Project Specification * Binary interface The VM does not use floating point numbers, it instead uses fixed point numbers. This is for portability reasons as some devices might not have a FPU in them especially microcontrollers and some retro game systems like the PS1. ** Numbers | type | size (bytes) | description | |------+--------------+---------------------------------------| | u8 | 1 | unsigned 8bit, alias =char= and =byte= | | bool | 1 | unsigned 8bit, =false= or =true= | | i8 | 1 | signed 8bit for interop | | u16 | 2 | unsigned 16bit for interop | | i16 | 2 | signed 16bit for interop | | u32 | 4 | unsigned 32bit, alias =nat= | | i32 | 4 | signed 32bit, alias =int= | | f32 | 4 | signed 32bit fixed number, alias =real= | * Memory Uses a harvard style archecture, meaning the code and ram memory are split up into two seperate blocks. In the C version you can see these are two seperate arrays 'code' and 'mem'. During compilation constants and local variables are put onto 'mem' * Opcodes | 2^n | count | |----+-------| | 2^3 | 8 | | 2^4 | 16 | | 2^5 | 32 | | 2^6 | 64 | | 2^8 | 128 | ** could be encoded - op type [this is to maximize jump immidate and load immidate size] - memory location - local value / register - local value type *** Simplest [opcode][dest][src1][src2] [8][8][8][8] *** Maximize inline jump and load-immidate [0 0 0 0 0 0 0 0][0 0 0 0 0 0 0 0][0 0 0 0 0 0 0 0][0 0 0 0 0 0 0 0] [0 0 0 | 0 0 0 0 0][0 0 0 | 0 0 0 0 0][0 0 0 | 0 0 0 0 0][0 0 0 | 0 0 0 | 0 0 ] noop [0 0 0 | 0 0 0 0 0][0 0 0 | 0 0 0 0 0][0 0 0 | 0 0 0 0 0][0 0 0 | 0 0 1 | 0 0 ] call [0 0 0 | 0 0 0 0 0][0 0 0 | 0 0 0 0 0][0 0 0 | 0 0 0 0 0][0 0 0 | 0 1 0 | 0 0 ] return [0 0 0 | 0 0 0 0 0][0 0 0 | 0 0 0 0 0][0 0 0 | 0 0 0 0 0][0 0 0 | 0 1 1 | 0 0 ] syscall? [0 0 0 | 0 0 0 0 0][0 0 0 | 0 0 0 0 0][0 0 0 | 0 0 0 0 1][0 0 0 | 1 0 0 | 0 0 ] exit [0 0 0 0 0 0 0 0][0 0 0 0 0 0 0 0][0 0 0 0 0 0 0 0][0 0 0 0 0 0 | 0 1 ] jump ~1GB range [0 0 0 0 0 0 0 0][0 0 0 0 0 0 0 0][0 0 0 0 0 0 0 0][0 0 0 0 0 0 | 1 0 ] load-immidate 2^30 max *** multibyte ops - ones that would be easier if they were multibyte - jump - load immidate - syscall - call 0 0 - system, lowest because lower opcodes are faster 0 1 - memory 1 0 - math 1 1 - jump [0 0][0 0 0 0 0 0] = [system][no op] [0 0][1 0 0 0 0 0] = [system][loadimm] [0 0][0 0 0 0 0 0] = [system][return] [0 0 0 | r r r r r][0 0 0 | r r r r r][0 0 0 | r r r r r][b b | t | o o o | 1 1] [math][add][f][8] [0 0 0 | 0 0 0 0 0][0 0 0 | 0 0 0 0 0][0 0 0 | 0 0 0 0 0][0 0 | 1 | 0 0 1 | 1 1] [math][add][f][8] [0 1][0 0 1][0][0 0] = [math][sub][f][16] [0 1][0 1 0][0][0 0] = [math][mul][f][32] [0 1][0 1 1][0][0 0] = [math][div][f][?] [0 1][1 0 0][0][0 0] = [math][and][f][?] [1 1][0][0 0][0 0] = [jmp][u][eq] [1 1][0][0 0][0 0] = [jmp][u][ne] [1 1][0][0 0][0 0] = [jmp][u][lt] [1 1][0][0 0][0 0] = [jmp][u][gt] [1 1][1][0 0 0][0 0] = [jmp][s][le] [1 1][1][0 0 0][0 0] = [jmp][s][ge] [1 1][1][0 0 0][0 0] = [jmp][s][] [1 1][1][0 0 0][0 0] = [jmp][s][] 3 2 2 1 [...] i 32 0 3 1 3 1 [...] u rl j [...] u ab j [...] u eq j [...] u nq j [...] u lt j [...] u le j [...] u gt j [...] u ge j [jmp][dest][18] [lli][dest][2] int 3 add sub mul div jeq jne jlt jle jgt jge