161 lines
6.2 KiB
Org Mode
161 lines
6.2 KiB
Org Mode
#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 |
|
||
|------+--------------+---------------------------------------|
|
||
| bool | 1 | unsigned 8bit, =false= or =true= |
|
||
| u8 | 1 | unsigned 8bit, alias =char= and =byte= |
|
||
| 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
|
||
|
||
*** All 32 bit instructions (registers are all 32 bit values)
|
||
**** Type A: [8:opcode][8:dest][8:src1][8:src2]
|
||
- call : dest num-of-args ptr-to-function
|
||
- return : dest return-arg 0
|
||
- syscall : id num-of-args ptr-to-memory
|
||
- load-indirect-8 : dest src1 0
|
||
- load-indirect-16 : dest src1 0
|
||
- load-indirect-32 : dest src1 0
|
||
- load-absolute-8 : dest src1 0
|
||
- load-absolute-16 : dest src1 0
|
||
- load-absolute-32 : dest src1 0
|
||
- load-offset-8 : dest src1 src2
|
||
- load-offset-16 : dest src1 src2
|
||
- load-offset-32 : dest src1 src2
|
||
- store-absolute-8 : dest src1 0
|
||
- store-indirect-8 : dest src1 0
|
||
- store-offset-8 : dest src1 src2
|
||
- store-absolute-16 : dest src1 0
|
||
- store-indirect-16 : dest src1 0
|
||
- store-offset-16 : dest src1 src2
|
||
- store-absolute-32 : dest src1 0
|
||
- store-indirect-32 : dest src1 0
|
||
- store-offset-32 : dest src1 src2
|
||
- alloc : dest size 0
|
||
- memset-8 : dest src1 count
|
||
- memset-16 : dest src1 count
|
||
- memset-32 : dest src1 count
|
||
- memcpy-8 : dest src1 count
|
||
- memcpy-16 : dest src1 count
|
||
- memcpy-32 : dest src1 count
|
||
- mov : dest src1 0
|
||
- add-int : dest src1 src2
|
||
- sub-int : dest src1 src2
|
||
- mul-int : dest src1 src2
|
||
- div-int : dest src1 src2
|
||
- neg-int : dest src1 src2
|
||
- abs-int : dest src1 src2
|
||
- add-nat : dest src1 src2
|
||
- sub-nat : dest src1 src2
|
||
- mul-nat : dest src1 src2
|
||
- div-nat : dest src1 src2
|
||
- neg-nat : dest src1 src2
|
||
- abs-nat : dest src1 src2
|
||
- add-real : dest src1 src2
|
||
- sub-real : dest src1 src2
|
||
- mul-real : dest src1 src2
|
||
- div-real : dest src1 src2
|
||
- neg-real : dest src1 src2
|
||
- abs-real : dest src1 src2
|
||
- int-to-real : dest src1 src2
|
||
- int-to-nat : dest src1 src2
|
||
- nat-to-real : dest src1 src2
|
||
- nat-to-int : dest src1 src2
|
||
- real-to-int : dest src1 src2
|
||
- real-to-nat : dest src1 src2
|
||
- shift-left : dest src1 src2
|
||
- shift-right : dest src1 src2
|
||
- shift-right-extend : dest src1 src2
|
||
- and : dest src1 src2
|
||
- or : dest src1 src2
|
||
- xor : dest src1 src2
|
||
- jump-absolute : dest 0 0
|
||
- jump-offset : dest src1 0
|
||
- jmp-flag : dest 0 0 | jump if flag > 0
|
||
- jeq-int : dest src1 src2
|
||
- jne-int : dest src1 src2
|
||
- jgt-int : dest src1 src2
|
||
- jlt-int : dest src1 src2
|
||
- jle-int : dest src1 src2
|
||
- jge-int : dest src1 src2
|
||
- jeq-nat : dest src1 src2
|
||
- jne-nat : dest src1 src2
|
||
- jgt-nat : dest src1 src2
|
||
- jlt-nat : dest src1 src2
|
||
- jle-nat : dest src1 src2
|
||
- jge-nat : dest src1 src2
|
||
- jeq-real : dest src1 src2
|
||
- jne-real : dest src1 src2
|
||
- jgt-real : dest src1 src2
|
||
- jlt-real : dest src1 src2
|
||
- jle-real : dest src1 src2
|
||
- jge-real : dest src1 src2
|
||
|
||
**** Type B: [8:opcode][8:dest][16:immediate]
|
||
- load-immediate : dest imm : for small 16 bit consts, and lower part of 32 bit consts
|
||
- load-upper-immediate : dest imm : for large 32 bit consts
|
||
|
||
**** Type C: [8:opcode][24:immediate]
|
||
- halt : immediate is unused (all zeros)
|
||
- jump-immediate : immediate jump
|
||
|
||
|
||
** Maybe more flexible calling convention?
|
||
|
||
At compile time each function gets N number of locals (up to 255). These are allocated onto memory along with everything else, but they come before the heap values.
|
||
|
||
Memory-to-memory with register characteristics?
|
||
|
||
Passed in values
|
||
|
||
Copy each argument from the callers local to the callees local. This includes pointers.
|
||
|
||
child modifies the heap
|
||
|
||
If a child modifies a value in the parents heap do nothing, this is expected behavior.
|
||
|
||
If a child changes the size of a parents heap then copy the heap value to the child’s frame.
|
||
|
||
Returned values
|
||
|
||
If a primitive value just copy from child local to parent local
|
||
|
||
If a heap value is returned but placed in a new local in the parent then copy the child to the parent and update the frames memory pointer
|
||
|
||
If a heap value is replaced (i.e. the return sets a heap value with its modified version) then
|
||
Sort each returned value by its pointers location in memory, lowest first
|
||
Move to position of returned values lowest ptr position.
|
||
Read fat ptr size of the earliest value.
|
||
Take the current size of heap.
|
||
Move to just after the end of the size + ptr.
|
||
Copy all values from that location through current end of heap to the old start location of that value.
|
||
Subtract the old size of the value from the mp.
|
||
Copy the new sized value and put it at the current end of the heap.
|
||
Update the new pointer’s local position.
|
||
Add the new size to the mp.
|
||
Repeat for each returned value that is a replaced heap value.
|
||
|