reqvm is a register based bytecode VM.
Floating point won't be supported for a while.
reqvm has a 8MiB stack, however the operations work on 8-byte integers, as such you can store 1'048'576 values on it.
Binaries start with a 256 byte preamble. I've no idea if I'll ever fill this up, but whatever.
Binaries will start with the following magic byte string !reqvm;VSszMEI2VSszMEVGVSszMEZDVSszMEVCVSszMEM5VSswMDIxVSs2NjQyVSszMDg4VSs2QjYyVSszMDdFVSszMDhDVSswMDIx\n.
Then a string of bytes following this format: !<major>;<minor>;<patch>;<enabled features>;. major, minor, and patch are 2-byte numbers. enabled features is a string of bytes, every byte represents an individual optional feature, and the presence of the byte enables it.
This is padded with noops until 256 bytes have been reached.
After that follows the program itself.
All registers will be 64bit. List of registers:
- 64 general purpose registers:
gp0..63 - 16 integer function argument registers:
ifa0..15 - program counter(read only):
pc - a register dedicated to the return value of the last function:
ire - the stack pointer:
sp(read only)
- CF("comparison flag") - stores the result of a comparison between two registers. Possible values(these will be reffered to as
cf::value):eq(equal),less(less than),gr(greater than).
| opcode(byte) | mnemonic | instruction | notes |
|---|---|---|---|
00 |
noop |
noop |
is a noop |
01 |
call |
call func_name |
calls the function func_name |
02 |
ret |
ret |
returns from a function, performing necessary cleanup |
10 |
io |
io op reg |
the io metainstruction expect a 1-byte argument after it called the op which represent the I/O operation to be performed. See I/O operations |
20 |
add |
add r1, r2 |
adds r1 and r2, stores result in r1 |
21 |
sub |
sub r1, r2 |
subtract r2 from r1, stores result in r1 |
22 |
mul |
mul r1, r2 |
multiplies r1 by r2, stores result in r1 |
23 |
div |
div r1, r2 |
divides r1 by r2, stores quotient in r1 |
24 |
mod |
mod r1, r2 |
divides r1 by r2, stores remainder in r1 |
25 |
and |
and r1, r2 |
bitwise ANDs r1 and r2, stores result in r1 |
26 |
or |
or r1, r2 |
bitwise ORs r1 and r2, stores result in r1 |
27 |
xor |
xor r1, r2 |
bitwise XORs r1 and r2, stores result in r1 |
28 |
not |
not r1 |
bitwise NOTs r1, stores result in r1 |
29 |
lshft |
lshft r1, r2 |
Performs r1 <<= r2 |
30 |
rshft |
rshft r1, r2 |
Performs r1 >>= r2 |
35 |
push |
push reg |
pushes reg onto the stack, increases the sp by 1 |
36 |
pushc |
pushc constant |
pushes the constant on the stack, stored in the binary as 8 bytes |
37 |
pop |
pop reg |
pops the top value from the stack into reg |
42 |
cmp |
cmp r1, r2 |
compares r1 and r2, stores result in CF |
43 |
jmp |
jmp label |
jumps to label |
44 |
jeq |
jeq label |
if CF == cf::eq, jumps to label |
45 |
jneq |
jneq label |
if CF != cf::eq jumps to label |
46 |
jl |
jl label |
if CF == cf::less, jumps to label |
47 |
jleq |
jleq label |
if CF == cf::less or CF == cf::eq, jumps to label |
48 |
jg |
jg label |
if CF == cf::gr, jumps to label |
49 |
jgeq |
jgeq label |
if CF == cf::gr or CF == cf::eq, jumps to label |
255 |
halt |
halt |
stops program execution, and the VM, returning the value in ire to the OS |
| byte | mnemonic | argument | notes |
|---|---|---|---|
01 |
getc |
a register | gets a character from stdin and stores it in the register passed as argument |
02 |
putc |
a register | interprets the register given as argument as an 8-bit character and outputs it to stdout |
03 |
put8c |
a register | interprets the register as a string of 8 8-bit characters and outputs them to stdout |
04 |
putn |
a register | interprets the register as a 64-bit number and outputs it to stdout |