Remove duplicate file, merge local
This commit is contained in:
parent
39d088bd9c
commit
f465cdb39a
134
'
134
'
|
|
@ -1,134 +0,0 @@
|
|||
#+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
|
||||
|
|
@ -184,3 +184,64 @@ 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.
|
||||
|
||||
Opcodes are variable sized, each part is 8 bytes to maximize portability.
|
||||
|
||||
8 bit
|
||||
Type Z: [u8:opcode]
|
||||
16 bit
|
||||
Type Q: [u8:opcode][u8:dest]
|
||||
24 bit
|
||||
Type I: [u8:opcode][u8:dest][u8:src1]
|
||||
32 bit
|
||||
Type M: [u8:opcode][u8:dest][u8:src1][u8:src2]
|
||||
40 bit
|
||||
Type J: [u8:opcode][u32:dest]
|
||||
56 bit
|
||||
Type S: [u8:opcode][u8:dest][u8:src1][u32:imm]
|
||||
|
||||
Fixed size
|
||||
|
||||
*** All 32 bit instructions (registers are all 32 bit values)
|
||||
**** Type I: [8:opcode][8:dest][16:immediate]
|
||||
- load-immediate : for small 16 bit consts, and lower part of 32 bit consts
|
||||
- load-upper-immediate : for large 32 bit consts
|
||||
- load-indirect : dest
|
||||
- store-indirect : dest
|
||||
- load-absolute : dest
|
||||
- store-absolute : dest
|
||||
- jump-absolute : dest
|
||||
|
||||
**** Type M: [8:opcode][8:dest][8:src1][8:src2]
|
||||
- load-offset dest src1 src2
|
||||
- store-offset dest src1 src2
|
||||
- call dest num-of-args ptr-to-function
|
||||
- return dest return-arg
|
||||
- syscall id num-of-args ptr-to-memory
|
||||
- memset dest src1 count
|
||||
- long-jump : src1 used as address
|
||||
- add
|
||||
- sub
|
||||
- mul
|
||||
- div
|
||||
- and
|
||||
- or
|
||||
- xor
|
||||
- shift-left
|
||||
- shift-right
|
||||
- shift-right-sign-extend
|
||||
- neg
|
||||
- abs
|
||||
- mov : move register value
|
||||
- alloc : dest size unused
|
||||
- jeq (jump eq)
|
||||
- jne (jump not eq)
|
||||
- jgt (jump greater than)
|
||||
- jlt (jump less than)
|
||||
- jle (jump less than or eq)
|
||||
- jge (jump greater then or eq)
|
||||
- jf (jump if flag < zero)
|
||||
|
||||
**** Type Z: [8:opcode][24:immediate]
|
||||
- noop : immediate is unused (all zeros)
|
||||
- jump : immediate jump
|
||||
|
|
|
|||
82
vm/vm.h
82
vm/vm.h
|
|
@ -4,17 +4,93 @@
|
|||
#include "libc.h"
|
||||
|
||||
typedef enum {
|
||||
NOOP
|
||||
OP_NOOP, /* noop : no nothing for 1 cycle */
|
||||
OP_CALL, /* call : creates a new frame */
|
||||
OP_RETURN, /* return : returns from a frame to the parent frame */
|
||||
OP_SYSCALL, /* syscall : syscall(u8 src1 count_args, u32 ptr_memory) */
|
||||
OP_LOAD_IMM, /* load_immediate : locals[dest] = constant */
|
||||
OP_LOAD_IND_8, /* load_indirect_8 : locals[dest] = memory[locals[src1]] as u8 */
|
||||
OP_LOAD_IND_16, /* load_indirect_16 : locals[dest] = memory[locals[src1]] as u16 */
|
||||
OP_LOAD_IND_32, /* load_indirect_32 : locals[dest] = memory[locals[src1]] as u32 */
|
||||
OP_LOAD_ABS_8, /* load_absolute_8 : locals[dest] = memory[src1] as u8 */
|
||||
OP_LOAD_ABS_16, /* load_absolute_16 : locals[dest] = memory[src1] as u16 */
|
||||
OP_LOAD_ABS_32, /* load_absolute_32 : locals[dest] = memory[src1] as u32 */
|
||||
OP_LOAD_OFF_8, /* load_offset_8 : locals[dest] = memory[locals[src1] + offset] as u8 */
|
||||
OP_LOAD_OFF_16, /* load_offset_16 : locals[dest] = memory[locals[src1] + offset] as u16 */
|
||||
OP_LOAD_OFF_32, /* load_offset_32 : locals[dest] = memory[locals[src1] + offset] as u32 */
|
||||
OP_STORE_ABS_8, /* store_absolute_8 : memory[dest] = src1 && 0xFF */
|
||||
OP_STORE_ABS_16, /* store_absolute_16 : memory[dest] = src1 && 0xFFFF */
|
||||
OP_STORE_ABS_32, /* store_absolute_32 : memory[dest] = src1 */
|
||||
OP_STORE_IND_8, /* store_indirect_8 : memory[dest] = locals[src1] && 0xFF */
|
||||
OP_STORE_IND_16, /* store_indirect_16 : memory[dest] = locals[src1] && 0xFFFF*/
|
||||
OP_STORE_IND_32, /* store_indirect_32 : memory[dest] = locals[src1] */
|
||||
OP_STORE_OFF_8, /* store_offset_8 : memory[locals[dest] + offset] = locals[src1] && 0xFF */
|
||||
OP_STORE_OFF_16, /* store_offset_16 : memory[locals[dest] + offset] = locals[src1] && 0xFFFF */
|
||||
OP_STORE_OFF_32, /* store_offset_32 : memory[locals[dest] + offset] = locals[src1] */
|
||||
OP_MALLOC, /* malloc : dest = fat ptr to memory of ((src1 as size) + 4) */
|
||||
OP_MEMSET_8, /* memset_8 : dest <-> dest+count = src1 as u8 */
|
||||
OP_MEMSET_16, /* memset_16 : dest <-> dest+count = src1 as u16 */
|
||||
OP_MEMSET_32, /* memset_32 : dest <-> dest+count = src1 as u32 */
|
||||
OP_REG_MOV, /* register_move : locals[dest] = locals[src1] */
|
||||
OP_ADD_INT, /* add_int : locals[dest] = locals[src1] + locals[src2] */
|
||||
OP_SUB_INT, /* sub_int : locals[dest] = locals[src1] _ locals[src2] */
|
||||
OP_MUL_INT, /* mul_int : locals[dest] = locals[src1] * locals[src2] */
|
||||
OP_DIV_INT, /* div_int : locals[dest] = locals[src1] / locals[src2] */
|
||||
OP_ABS_INT, /* abs_int : locals[dest] = | locals[src1] | */
|
||||
OP_NEG_INT, /* neg_int : locals[dest] = -locals[src1] */
|
||||
OP_ADD_NAT, /* add_nat : locals[dest] = locals[src1] + locals[src2] */
|
||||
OP_SUB_NAT, /* sub_nat : locals[dest] = locals[src1] _ locals[src2] */
|
||||
OP_MUL_NAT, /* mul_nat : locals[dest] = locals[src1] * locals[src2] */
|
||||
OP_DIV_NAT, /* div_nat : locals[dest] = locals[src1] / locals[src2] */
|
||||
OP_ABS_NAT, /* abs_nat : locals[dest] = | locals[src1] | */
|
||||
OP_NEG_NAT, /* neg_nat : locals[dest] = -locals[src1] */
|
||||
OP_ADD_REAL, /* add_real : locals[dest] = locals[src1] + locals[src2] */
|
||||
OP_SUB_REAL, /* sub_real : locals[dest] = locals[src1] _ locals[src2] */
|
||||
OP_MUL_REAL, /* mul_real : locals[dest] = locals[src1] * locals[src2] */
|
||||
OP_DIV_REAL, /* div_real : locals[dest] = locals[src1] / locals[src2] */
|
||||
OP_ABS_REAL, /* abs_real : locals[dest] = | locals[src1] | */
|
||||
OP_NEG_REAL, /* neg_real : locals[dest] = _locals[src1] */
|
||||
OP_INT_TO_REAL, /* int_to_real : locals[dest] = locals[src1] as real */
|
||||
OP_INT_TO_NAT, /* int_to_nat : locals[dest] = locals[src1] as nat */
|
||||
OP_NAT_TO_REAL, /* nat_to_real : locals[dest] = locals[src1] as real */
|
||||
OP_NAT_TO_INT, /* nat_to_int : locals[dest] = locals[src1] as int */
|
||||
OP_REAL_TO_INT, /* real_to_int : locals[dest] = locals[src1] as int */
|
||||
OP_REAL_TO_NAT, /* real_to_nat : locals[dest] = locals[src1] as nat */
|
||||
OP_BIT_SHIFT_LEFT, /* bit_shift_left : locals[dest] = locals[src1] << locals[src2] */
|
||||
OP_BIT_SHIFT_RIGHT,/* bit_shift_right : locals[dest] = locals[src1] >> locals[src2] */
|
||||
OP_BIT_SHIFT_R_EXT,/* bit_shift_r_ext : locals[dest] as i32 = locals[src1] >> locals[src2] */
|
||||
OP_BAND, /* bit_and : locals[dest] = locals[src1] & locals[src2] */
|
||||
OP_BOR, /* bit_or : locals[dest] = locals[src1] | locals[src2] */
|
||||
OP_BXOR, /* bit_xor : locals[dest] = locals[src1] ^ locals[src2] */
|
||||
OP_JMP, /* jump : jump to &dest unconditionally */
|
||||
OP_JMPF, /* jump_if_flag : jump to &dest if flag != 0 */
|
||||
OP_JEQ_INT, /* jump_eq_int : jump to &dest if locals[src1] as int == locals[src2] as int */
|
||||
OP_JNEQ_INT, /* jump_neq_int : jump to &dest if locals[src1] as int != locals[src2] as int */
|
||||
OP_JGT_INT, /* jump_gt_int : jump to &dest if locals[src1] as int > locals[src2] as int */
|
||||
OP_JLT_INT, /* jump_lt_int : jump to &dest if locals[src1] as int < locals[src2] as int */
|
||||
OP_JLE_INT, /* jump_le_int : jump to &dest if locals[src1] as int <= locals[src2] as int */
|
||||
OP_JGE_INT, /* jump_ge_int : jump to &dest if locals[src1] as int >= locals[src2] as int */
|
||||
OP_JEQ_NAT, /* jump_eq_nat : jump to &dest if locals[src1] as nat == locals[src2] as nat */
|
||||
OP_JNEQ_NAT, /* jump_neq_nat : jump to &dest if locals[src1] as nat != locals[src2] as nat */
|
||||
OP_JGT_NAT, /* jump_gt_nat : jump to &dest if locals[src1] as nat > locals[src2] as nat */
|
||||
OP_JLT_NAT, /* jump_lt_nat : jump to &dest if locals[src1] as nat < locals[src2] as nat */
|
||||
OP_JLE_NAT, /* jump_le_nat : jump to &dest if locals[src1] as nat <= locals[src2] as nat */
|
||||
OP_JGE_NAT, /* jump_ge_nat : jump to &dest if locals[src1] as nat >= locals[src2] as nat */
|
||||
OP_JEQ_REAL, /* jump_eq_real : jump to &dest if locals[src1] as real == locals[src2] as real */
|
||||
OP_JNEQ_REAL, /* jump_neq_real : jump to &dest if locals[src1] as real != locals[src2] as real */
|
||||
OP_JGE_REAL, /* jump_ge_real : jump to &dest if locals[src1] as real >= locals[src2] as real */
|
||||
OP_JGT_REAL, /* jump_gt_real : jump to &dest if locals[src1] as real > locals[src2] as real */
|
||||
OP_JLT_REAL, /* jump_lt_real : jump to &dest if locals[src1] as real < locals[src2] as real */
|
||||
OP_JLE_REAL, /* jump_le_real : jump to &dest if locals[src1] as real <= locals[src2] as real */
|
||||
OP_MAX_OPCODE /* not really an opcode but used to check max length of ops */
|
||||
} Opcode;
|
||||
|
||||
typedef struct vm_s VM;
|
||||
|
||||
#define CODE_SIZE 4096
|
||||
#define MEM_SIZE 65536
|
||||
|
||||
struct vm_s {
|
||||
u32 pc;
|
||||
u32 code[CODE_SIZE];
|
||||
u8 mem[MEM_SIZE];
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue