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.
|
Update the new pointer’s local position.
|
||||||
Add the new size to the mp.
|
Add the new size to the mp.
|
||||||
Repeat for each returned value that is a replaced heap value.
|
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"
|
#include "libc.h"
|
||||||
|
|
||||||
typedef enum {
|
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;
|
} Opcode;
|
||||||
|
|
||||||
typedef struct vm_s VM;
|
typedef struct vm_s VM;
|
||||||
|
|
||||||
#define CODE_SIZE 4096
|
|
||||||
#define MEM_SIZE 65536
|
#define MEM_SIZE 65536
|
||||||
|
|
||||||
struct vm_s {
|
struct vm_s {
|
||||||
u32 pc;
|
u32 pc;
|
||||||
u32 code[CODE_SIZE];
|
|
||||||
u8 mem[MEM_SIZE];
|
u8 mem[MEM_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue