Add opcodes, get rid of VM for less redirection, add encode/decode macros
This commit is contained in:
parent
f465cdb39a
commit
6b625c4663
|
|
@ -11,8 +11,8 @@ especially microcontrollers and some retro game systems like the PS1.
|
||||||
** Numbers
|
** Numbers
|
||||||
| type | size (bytes) | description |
|
| type | size (bytes) | description |
|
||||||
|------+--------------+---------------------------------------|
|
|------+--------------+---------------------------------------|
|
||||||
| u8 | 1 | unsigned 8bit, alias =char= and =byte= |
|
|
||||||
| bool | 1 | unsigned 8bit, =false= or =true= |
|
| bool | 1 | unsigned 8bit, =false= or =true= |
|
||||||
|
| u8 | 1 | unsigned 8bit, alias =char= and =byte= |
|
||||||
| i8 | 1 | signed 8bit for interop |
|
| i8 | 1 | signed 8bit for interop |
|
||||||
| u16 | 2 | unsigned 16bit for interop |
|
| u16 | 2 | unsigned 16bit for interop |
|
||||||
| i16 | 2 | signed 16bit for interop |
|
| i16 | 2 | signed 16bit for interop |
|
||||||
|
|
@ -30,130 +30,103 @@ 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'
|
During compilation constants and local variables are put onto 'mem'
|
||||||
|
|
||||||
* Opcodes
|
* 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
|
||||||
|
|
||||||
| 2^n | count |
|
**** Type B: [8:opcode][8:dest][16:immediate]
|
||||||
|----+-------|
|
- load-immediate : dest imm : for small 16 bit consts, and lower part of 32 bit consts
|
||||||
| 2^3 | 8 |
|
- load-upper-immediate : dest imm : for large 32 bit consts
|
||||||
| 2^4 | 16 |
|
|
||||||
| 2^5 | 32 |
|
|
||||||
| 2^6 | 64 |
|
|
||||||
| 2^8 | 128 |
|
|
||||||
|
|
||||||
** could be encoded
|
**** Type C: [8:opcode][24:immediate]
|
||||||
- op type [this is to maximize jump immidate and load immidate size]
|
- halt : immediate is unused (all zeros)
|
||||||
- memory location
|
- jump-immediate : immediate jump
|
||||||
- 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]
|
|
||||||
|
|
||||||
|
|
||||||
J [0 0 0 0 0 0 0 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]
|
|
||||||
L [0 0 0 0 0 0 0 0][0 0 0 0 0 0 0 0][0 0 0 0 0 0 0 0][0 | o o o o o | 1 0]
|
|
||||||
|
|
||||||
R [r r r r r r | r r][r r r r | r r r r][r r | b b | 0 0 0 0][o o o o o o | 1 1]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[0 0 0 0 0 | r r r][r r r r | r r r r][r r | r r r r r r][b b | t | o o o | 1 1]
|
|
||||||
|
|
||||||
[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]
|
|
||||||
[0 0 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 0 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 1 0 | 1 1] [math][sub][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 1 1 | 1 1] [math][mul][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 | 1 0 0 | 1 1] [math][div][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 | 1 0 1 | 1 1] [math][mod][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
|
|
||||||
|
|
||||||
Maybe opcodes could be Huffman encoded? That way the smaller opcodes get more operand data within the u32
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
Maybe instead of push pushing onto a stack it instead pushes onto a child frame? Pops would just mark what locals need to be replaced by the child function? Maybe we can get rid of call/return and just use jumps?
|
|
||||||
|
|
||||||
U8 u8 u8 u8
|
|
||||||
Push/pop parent_local child_local metadata
|
|
||||||
|
|
||||||
** Maybe more flexible calling convention?
|
** 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?
|
Memory-to-memory with register characteristics?
|
||||||
|
|
||||||
Passed in values
|
Passed in values
|
||||||
|
|
@ -185,63 +158,3 @@ 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
|
|
||||||
|
|
|
||||||
185
vm/vm.c
185
vm/vm.c
|
|
@ -1,6 +1,187 @@
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
|
|
||||||
bool step_vm(VM *vm) {
|
u32 mp; /* memory pointer */
|
||||||
USED(vm);
|
u32 cp; /* code pointer */
|
||||||
|
u32 pc; /* program counter */
|
||||||
|
u32 flag; /* flag */
|
||||||
|
u32 *code; /* code */
|
||||||
|
u8 *mem; /* memory */
|
||||||
|
|
||||||
|
bool step_vm() {
|
||||||
|
|
||||||
|
u32 instruction = code[pc];
|
||||||
|
u8 opcode = DECODE_OP(instruction);
|
||||||
|
|
||||||
|
switch (opcode) {
|
||||||
|
case OP_HALT: {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case OP_CALL: {
|
||||||
|
|
||||||
|
}
|
||||||
|
case OP_RETURN: {
|
||||||
|
}
|
||||||
|
case OP_SYSCALL: {
|
||||||
|
}
|
||||||
|
case OP_LOAD_IMM: {
|
||||||
|
}
|
||||||
|
case OP_LOAD_UPPER_IMM: {
|
||||||
|
}
|
||||||
|
case OP_LOAD_IND_8: {
|
||||||
|
}
|
||||||
|
case OP_LOAD_IND_16: {
|
||||||
|
}
|
||||||
|
case OP_LOAD_IND_32: {
|
||||||
|
}
|
||||||
|
case OP_LOAD_ABS_8: {
|
||||||
|
}
|
||||||
|
case OP_LOAD_ABS_16: {
|
||||||
|
}
|
||||||
|
case OP_LOAD_ABS_32: {
|
||||||
|
}
|
||||||
|
case OP_LOAD_OFF_8: {
|
||||||
|
}
|
||||||
|
case OP_LOAD_OFF_16: {
|
||||||
|
}
|
||||||
|
case OP_LOAD_OFF_32: {
|
||||||
|
}
|
||||||
|
case OP_STORE_ABS_8: {
|
||||||
|
}
|
||||||
|
case OP_STORE_ABS_16: {
|
||||||
|
}
|
||||||
|
case OP_STORE_ABS_32: {
|
||||||
|
}
|
||||||
|
case OP_STORE_IND_8: {
|
||||||
|
}
|
||||||
|
case OP_STORE_IND_16: {
|
||||||
|
}
|
||||||
|
case OP_STORE_IND_32: {
|
||||||
|
}
|
||||||
|
case OP_STORE_OFF_8: {
|
||||||
|
}
|
||||||
|
case OP_STORE_OFF_16: {
|
||||||
|
}
|
||||||
|
case OP_STORE_OFF_32: {
|
||||||
|
}
|
||||||
|
case OP_MEM_ALLOC: {
|
||||||
|
}
|
||||||
|
case OP_MEM_CPY: {
|
||||||
|
}
|
||||||
|
case OP_MEM_SET_8: {
|
||||||
|
}
|
||||||
|
case OP_MEM_SET_16: {
|
||||||
|
}
|
||||||
|
case OP_MEM_SET_32: {
|
||||||
|
}
|
||||||
|
case OP_REG_MOV: {
|
||||||
|
}
|
||||||
|
case OP_ADD_INT: {
|
||||||
|
}
|
||||||
|
case OP_SUB_INT: {
|
||||||
|
}
|
||||||
|
case OP_MUL_INT: {
|
||||||
|
}
|
||||||
|
case OP_DIV_INT: {
|
||||||
|
}
|
||||||
|
case OP_ABS_INT: {
|
||||||
|
}
|
||||||
|
case OP_NEG_INT: {
|
||||||
|
}
|
||||||
|
case OP_ADD_NAT: {
|
||||||
|
}
|
||||||
|
case OP_SUB_NAT: {
|
||||||
|
}
|
||||||
|
case OP_MUL_NAT: {
|
||||||
|
}
|
||||||
|
case OP_DIV_NAT: {
|
||||||
|
}
|
||||||
|
case OP_ABS_NAT: {
|
||||||
|
}
|
||||||
|
case OP_NEG_NAT: {
|
||||||
|
}
|
||||||
|
case OP_ADD_REAL: {
|
||||||
|
}
|
||||||
|
case OP_SUB_REAL: {
|
||||||
|
}
|
||||||
|
case OP_MUL_REAL: {
|
||||||
|
}
|
||||||
|
case OP_DIV_REAL: {
|
||||||
|
}
|
||||||
|
case OP_ABS_REAL: {
|
||||||
|
}
|
||||||
|
case OP_NEG_REAL: {
|
||||||
|
}
|
||||||
|
case OP_INT_TO_REAL: {
|
||||||
|
}
|
||||||
|
case OP_INT_TO_NAT: {
|
||||||
|
}
|
||||||
|
case OP_NAT_TO_REAL: {
|
||||||
|
}
|
||||||
|
case OP_NAT_TO_INT: {
|
||||||
|
}
|
||||||
|
case OP_REAL_TO_INT: {
|
||||||
|
}
|
||||||
|
case OP_REAL_TO_NAT: {
|
||||||
|
}
|
||||||
|
case OP_BIT_SHIFT_LEFT: {
|
||||||
|
}
|
||||||
|
case OP_BIT_SHIFT_RIGHT: {
|
||||||
|
}
|
||||||
|
case OP_BIT_SHIFT_R_EXT: {
|
||||||
|
}
|
||||||
|
case OP_BIT_AND: {
|
||||||
|
}
|
||||||
|
case OP_BIT_OR: {
|
||||||
|
}
|
||||||
|
case OP_BIT_XOR: {
|
||||||
|
}
|
||||||
|
case OP_JMP_IMM: {
|
||||||
|
}
|
||||||
|
case OP_JMP_ABS: {
|
||||||
|
}
|
||||||
|
case OP_JMP_OFF: {
|
||||||
|
}
|
||||||
|
case OP_JMP_FLAG: {
|
||||||
|
}
|
||||||
|
case OP_JEQ_INT: {
|
||||||
|
}
|
||||||
|
case OP_JNE_INT: {
|
||||||
|
}
|
||||||
|
case OP_JGT_INT: {
|
||||||
|
}
|
||||||
|
case OP_JLT_INT: {
|
||||||
|
}
|
||||||
|
case OP_JLE_INT: {
|
||||||
|
}
|
||||||
|
case OP_JGE_INT: {
|
||||||
|
}
|
||||||
|
case OP_JEQ_NAT: {
|
||||||
|
}
|
||||||
|
case OP_JNE_NAT: {
|
||||||
|
}
|
||||||
|
case OP_JGT_NAT: {
|
||||||
|
}
|
||||||
|
case OP_JLT_NAT: {
|
||||||
|
}
|
||||||
|
case OP_JLE_NAT: {
|
||||||
|
}
|
||||||
|
case OP_JGE_NAT: {
|
||||||
|
}
|
||||||
|
case OP_JEQ_REAL: {
|
||||||
|
}
|
||||||
|
case OP_JNE_REAL: {
|
||||||
|
}
|
||||||
|
case OP_JGE_REAL: {
|
||||||
|
}
|
||||||
|
case OP_JGT_REAL: {
|
||||||
|
}
|
||||||
|
case OP_JLT_REAL: {
|
||||||
|
}
|
||||||
|
case OP_JLE_REAL: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* something went very wrong */
|
||||||
|
flag = 255;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
246
vm/vm.h
246
vm/vm.h
|
|
@ -3,98 +3,168 @@
|
||||||
|
|
||||||
#include "libc.h"
|
#include "libc.h"
|
||||||
|
|
||||||
typedef enum {
|
/**
|
||||||
OP_NOOP, /* noop : no nothing for 1 cycle */
|
* Instruction Types
|
||||||
OP_CALL, /* call : creates a new frame */
|
*
|
||||||
OP_RETURN, /* return : returns from a frame to the parent frame */
|
* A : [8:opcode][8:dest][8:src1][8:src2]
|
||||||
OP_SYSCALL, /* syscall : syscall(u8 src1 count_args, u32 ptr_memory) */
|
* B : [8:opcode][8:dest][16:immediate]
|
||||||
OP_LOAD_IMM, /* load_immediate : locals[dest] = constant */
|
* C : [8:opcode][24:immediate]
|
||||||
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 */
|
#define DECODE_OP(instruction) ((((u32)(instruction)) >> 24) & 0xFF)
|
||||||
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 ENCODE_A(opcode, dest, src1, src2) ((((u32)(opcode) & 0xFF) << 24) | \
|
||||||
|
(((u32)(dest) & 0xFF) << 16) | \
|
||||||
|
(((u32)(src1) & 0xFF) << 8) | \
|
||||||
|
(((u32)(src2) & 0xFF)))
|
||||||
|
|
||||||
|
#define DECODE_A(instruction) \
|
||||||
|
u8 dest = (((u32)(instruction)) >> 16) & 0xFF; \
|
||||||
|
u8 src1 = (((u32)(instruction)) >> 8) & 0xFF; \
|
||||||
|
u8 src2 = ((u32)(instruction)) & 0xFF;
|
||||||
|
|
||||||
|
#define ENCODE_B(opcode, dest, imm) ((((u32)(opcode) & 0xFF) << 24) | \
|
||||||
|
(((u32)(dest) & 0xFF) << 16) | \
|
||||||
|
(((u32)(imm)) & 0xFFFF))
|
||||||
|
#define DECODE_B(instruction) \
|
||||||
|
u8 dest = (((u32)(instruction)) >> 16) & 0xFF; \
|
||||||
|
u16 imm = ((u32)(instruction)) & 0xFFFF;
|
||||||
|
|
||||||
|
#define ENCODE_C(opcode, imm) ((((u32)(opcode) & 0xFF) << 24) | \
|
||||||
|
(((u32)(imm)) & 0xFFFFFF))
|
||||||
|
#define DECODE_C(instruction) \
|
||||||
|
u32 imm = ((u32)(instruction)) & 0xFFFFFF;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
OP_HALT, /* halt : C : all zeros : halt execution */
|
||||||
|
OP_CALL, /* call : A : dest args fn_ptr : creates a new frame */
|
||||||
|
OP_RETURN, /* return : A : dest args : returns from a frame to the parent frame */
|
||||||
|
OP_SYSCALL, /* syscall : A : id args mem_ptr : does a system call based on id with args */
|
||||||
|
OP_LOAD_IMM, /* load_immediate : B : locals[dest] = const as u16 */
|
||||||
|
OP_LOAD_UPPER_IMM, /* load_upper_immediate : B : locals[dest] = const as u32 << 16 | u16 */
|
||||||
|
OP_LOAD_IND_8, /* load_indirect_8 : A : locals[dest] = memory[locals[src1]] as u8 */
|
||||||
|
OP_LOAD_IND_16, /* load_indirect_16 : A : locals[dest] = memory[locals[src1]] as u16 */
|
||||||
|
OP_LOAD_IND_32, /* load_indirect_32 : A : locals[dest] = memory[locals[src1]] as u32 */
|
||||||
|
OP_LOAD_ABS_8, /* load_absolute_8 : A : locals[dest] = memory[src1] as u8 */
|
||||||
|
OP_LOAD_ABS_16, /* load_absolute_16 : A : locals[dest] = memory[src1] as u16 */
|
||||||
|
OP_LOAD_ABS_32, /* load_absolute_32 : A : locals[dest] = memory[src1] as u32 */
|
||||||
|
OP_LOAD_OFF_8, /* load_offset_8 : A : locals[dest] = memory[locals[src1] + offset] as u8 */
|
||||||
|
OP_LOAD_OFF_16, /* load_offset_16 : A : locals[dest] = memory[locals[src1] + offset] as u16 */
|
||||||
|
OP_LOAD_OFF_32, /* load_offset_32 : A : locals[dest] = memory[locals[src1] + offset] as u32 */
|
||||||
|
OP_STORE_ABS_8, /* store_absolute_8 : A : memory[dest] = src1 && 0xFF */
|
||||||
|
OP_STORE_ABS_16, /* store_absolute_16 : A : memory[dest] = src1 && 0xFFFF */
|
||||||
|
OP_STORE_ABS_32, /* store_absolute_32 : A : memory[dest] = src1 */
|
||||||
|
OP_STORE_IND_8, /* store_indirect_8 : A : memory[dest] = locals[src1] && 0xFF */
|
||||||
|
OP_STORE_IND_16, /* store_indirect_16 : A : memory[dest] = locals[src1] && 0xFFFF*/
|
||||||
|
OP_STORE_IND_32, /* store_indirect_32 : A : memory[dest] = locals[src1] */
|
||||||
|
OP_STORE_OFF_8, /* store_offset_8 : A : memory[locals[dest] + offset] = locals[src1] && 0xFF */
|
||||||
|
OP_STORE_OFF_16, /* store_offset_16 : A : memory[locals[dest] + offset] = locals[src1] && 0xFFFF */
|
||||||
|
OP_STORE_OFF_32, /* store_offset_32 : A : memory[locals[dest] + offset] = locals[src1] */
|
||||||
|
OP_MEM_ALLOC, /* alloc : A : memory[dest] = [locals[src1] as size + 4] */
|
||||||
|
OP_MEM_CPY, /* memcpy : A : memory[src1 .. src1 + count] = memory[dest .. dest + count] */
|
||||||
|
OP_MEM_SET_8, /* memset_8 : A : memory[dest .. dest + count] = local[src1] as u8 */
|
||||||
|
OP_MEM_SET_16, /* memset_16 : A : memory[dest .. dest + count] = local[src1] as u16 */
|
||||||
|
OP_MEM_SET_32, /* memset_32 : A : memory[dest .. dest + count] = local[src1] as u32 */
|
||||||
|
OP_REG_MOV, /* register_move : A : locals[dest] = locals[src1] */
|
||||||
|
OP_ADD_INT, /* add_int : A : locals[dest] = locals[src1] + locals[src2] */
|
||||||
|
OP_SUB_INT, /* sub_int : A : locals[dest] = locals[src1] - locals[src2] */
|
||||||
|
OP_MUL_INT, /* mul_int : A : locals[dest] = locals[src1] * locals[src2] */
|
||||||
|
OP_DIV_INT, /* div_int : A : locals[dest] = locals[src1] / locals[src2] */
|
||||||
|
OP_ABS_INT, /* abs_int : A : locals[dest] = | locals[src1] | */
|
||||||
|
OP_NEG_INT, /* neg_int : A : locals[dest] = -locals[src1] */
|
||||||
|
OP_ADD_NAT, /* add_nat : A : locals[dest] = locals[src1] + locals[src2] */
|
||||||
|
OP_SUB_NAT, /* sub_nat : A : locals[dest] = locals[src1] - locals[src2] */
|
||||||
|
OP_MUL_NAT, /* mul_nat : A : locals[dest] = locals[src1] * locals[src2] */
|
||||||
|
OP_DIV_NAT, /* div_nat : A : locals[dest] = locals[src1] / locals[src2] */
|
||||||
|
OP_ABS_NAT, /* abs_nat : A : locals[dest] = | locals[src1] | */
|
||||||
|
OP_NEG_NAT, /* neg_nat : A : locals[dest] = -locals[src1] */
|
||||||
|
OP_ADD_REAL, /* add_real : A : locals[dest] = locals[src1] + locals[src2] */
|
||||||
|
OP_SUB_REAL, /* sub_real : A : locals[dest] = locals[src1] - locals[src2] */
|
||||||
|
OP_MUL_REAL, /* mul_real : A : locals[dest] = locals[src1] * locals[src2] */
|
||||||
|
OP_DIV_REAL, /* div_real : A : locals[dest] = locals[src1] / locals[src2] */
|
||||||
|
OP_ABS_REAL, /* abs_real : A : locals[dest] = | locals[src1] | */
|
||||||
|
OP_NEG_REAL, /* neg_real : A : locals[dest] = -locals[src1] */
|
||||||
|
OP_INT_TO_REAL, /* int_to_real : A : locals[dest] = locals[src1] as real */
|
||||||
|
OP_INT_TO_NAT, /* int_to_nat : A : locals[dest] = locals[src1] as nat */
|
||||||
|
OP_NAT_TO_REAL, /* nat_to_real : A : locals[dest] = locals[src1] as real */
|
||||||
|
OP_NAT_TO_INT, /* nat_to_int : A : locals[dest] = locals[src1] as int */
|
||||||
|
OP_REAL_TO_INT, /* real_to_int : A : locals[dest] = locals[src1] as int */
|
||||||
|
OP_REAL_TO_NAT, /* real_to_nat : A : locals[dest] = locals[src1] as nat */
|
||||||
|
OP_BIT_SHIFT_LEFT, /* bit_shift_left : A : locals[dest] = locals[src1] << locals[src2] */
|
||||||
|
OP_BIT_SHIFT_RIGHT,/* bit_shift_right : A : locals[dest] = locals[src1] >> locals[src2] */
|
||||||
|
OP_BIT_SHIFT_R_EXT,/* bit_shift_r_ext : A : locals[dest] as i32 = locals[src1] >> locals[src2] */
|
||||||
|
OP_BIT_AND, /* bit_and : A : locals[dest] = locals[src1] & locals[src2] */
|
||||||
|
OP_BIT_OR, /* bit_or : A : locals[dest] = locals[src1] | locals[src2] */
|
||||||
|
OP_BIT_XOR, /* bit_xor : A : locals[dest] = locals[src1] ^ locals[src2] */
|
||||||
|
OP_JMP_IMM, /* jump_immediate : C : jump to imm unconditionally */
|
||||||
|
OP_JMP_ABS, /* jump_absolute : A : jump to locals[dest] unconditionally */
|
||||||
|
OP_JMP_OFF, /* jump_offset : A : jump to locals[dest] + locals[src1] unconditionally */
|
||||||
|
OP_JMP_FLAG, /* jump_if_flag : A : jump to locals[dest] if flag > 0 */
|
||||||
|
OP_JEQ_INT, /* jump_eq_int : A : jump to locals[dest] if locals[src1] as int == locals[src2] as int */
|
||||||
|
OP_JNE_INT, /* jump_neq_int : A : jump to locals[dest] if locals[src1] as int != locals[src2] as int */
|
||||||
|
OP_JGT_INT, /* jump_gt_int : A : jump to locals[dest] if locals[src1] as int > locals[src2] as int */
|
||||||
|
OP_JLT_INT, /* jump_lt_int : A : jump to locals[dest] if locals[src1] as int < locals[src2] as int */
|
||||||
|
OP_JLE_INT, /* jump_le_int : A : jump to locals[dest] if locals[src1] as int <= locals[src2] as int */
|
||||||
|
OP_JGE_INT, /* jump_ge_int : A : jump to locals[dest] if locals[src1] as int >= locals[src2] as int */
|
||||||
|
OP_JEQ_NAT, /* jump_eq_nat : A : jump to locals[dest] if locals[src1] as nat == locals[src2] as nat */
|
||||||
|
OP_JNE_NAT, /* jump_neq_nat : A : jump to locals[dest] if locals[src1] as nat != locals[src2] as nat */
|
||||||
|
OP_JGT_NAT, /* jump_gt_nat : A : jump to locals[dest] if locals[src1] as nat > locals[src2] as nat */
|
||||||
|
OP_JLT_NAT, /* jump_lt_nat : A : jump to locals[dest] if locals[src1] as nat < locals[src2] as nat */
|
||||||
|
OP_JLE_NAT, /* jump_le_nat : A : jump to locals[dest] if locals[src1] as nat <= locals[src2] as nat */
|
||||||
|
OP_JGE_NAT, /* jump_ge_nat : A : jump to locals[dest] if locals[src1] as nat >= locals[src2] as nat */
|
||||||
|
OP_JEQ_REAL, /* jump_eq_real : A : jump to locals[dest] if locals[src1] as real == locals[src2] as real */
|
||||||
|
OP_JNE_REAL, /* jump_neq_real : A : jump to locals[dest] if locals[src1] as real != locals[src2] as real */
|
||||||
|
OP_JGE_REAL, /* jump_ge_real : A : jump to locals[dest] if locals[src1] as real >= locals[src2] as real */
|
||||||
|
OP_JGT_REAL, /* jump_gt_real : A : jump to locals[dest] if locals[src1] as real > locals[src2] as real */
|
||||||
|
OP_JLT_REAL, /* jump_lt_real : A : jump to locals[dest] if locals[src1] as real < locals[src2] as real */
|
||||||
|
OP_JLE_REAL, /* jump_le_real : A : jump to locals[dest] if locals[src1] as real <= locals[src2] as real */
|
||||||
|
OP_MAX_OPCODE /* not an opcode count of instructions */
|
||||||
|
} Opcode;
|
||||||
|
|
||||||
#define MEM_SIZE 65536
|
#define MEM_SIZE 65536
|
||||||
|
|
||||||
struct vm_s {
|
extern u32 mp; /* memory pointer */
|
||||||
u32 pc;
|
extern u32 cp; /* code pointer */
|
||||||
u8 mem[MEM_SIZE];
|
extern u32 pc; /* program counter */
|
||||||
};
|
extern u32 flag; /* flag */
|
||||||
|
extern u32 *code; /* code */
|
||||||
|
extern u8 *mem; /* memory */
|
||||||
|
|
||||||
extern bool init_vm(VM *vm);
|
#define read_u8(addr) (mem[addr])
|
||||||
bool step_vm(VM *vm);
|
|
||||||
|
#define read_u16(addr) \
|
||||||
|
(((u16)mem[(addr) + 1] << 8) | ((u16)mem[(addr)]))
|
||||||
|
|
||||||
|
#define read_u32(addr) \
|
||||||
|
(((u32)mem[(addr) + 3] << 24) | \
|
||||||
|
((u32)mem[(addr) + 2] << 16) | \
|
||||||
|
((u32)mem[(addr) + 1] << 8) | ((u32)mem[(addr)]))
|
||||||
|
|
||||||
|
#define write_u8(addr, value) \
|
||||||
|
do { \
|
||||||
|
if ((addr) < sizeof(mem)) { \
|
||||||
|
mem[(addr)] = (value) & 0xFF; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define write_u16(addr, value) \
|
||||||
|
do { \
|
||||||
|
if ((addr) + 1 < sizeof(mem)) { \
|
||||||
|
mem[(addr)] = (value) & 0xFF; \
|
||||||
|
mem[(addr) + 1] = ((value) >> 8) & 0xFF; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define write_u32(addr, value) \
|
||||||
|
do { \
|
||||||
|
if ((addr) + 3 < sizeof(mem)) { \
|
||||||
|
mem[(addr)] = (value) & 0xFF; \
|
||||||
|
mem[(addr) + 1] = ((value) >> 8) & 0xFF; \
|
||||||
|
mem[(addr) + 2] = ((value) >> 16) & 0xFF; \
|
||||||
|
mem[(addr) + 3] = ((value) >> 24) & 0xFF; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
extern bool init_vm();
|
||||||
|
bool step_vm();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue