undar-lang/'

135 lines
3.4 KiB
Plaintext

#+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