4.2 KiB
4.2 KiB
VM
This is an outline of the VM that drives this language.
Primitives
- Numbers may be big endian (BE) or little endian (LE) at the byte level. This guide will use LE.
- Addresses point to single bytes.
- Signed numbers use two's complement.
| Type | Size (bits) |
|---|---|
| Address | 64 |
| Word | 64 |
| Halfword | 32 |
| Byte | 8 |
Registers
CPU registers are addressed by a value between 0-63 (6 bits). All registers are 64 bits wide.
- IP - Instruction pointer
- SP - Stack pointer
- FP - Frame pointer
- FLAGS - CPU flags
- (9 unused registers)
- STATUS - Generic status code
- R0-R49
CPU Flags
CPU flags are addressed by bit index, going from right to left.
00- Halt flag01- Compare flag
Flag ideas
- "Trace" flag - halts the CPU when certain conditions are met that may be causing undesired
behavior - for debugging
- Overwriting a register without its value being used
- Mixing arithmetic with bit twiddling on the same target
Instructions
Arithmetic
Arithmetic instructions store their result in the first register specified. Overflow is handled by wrapping around to 0.
- Add
- Params: REG1, REG2
REG1 = REG1 + REG2- Unsigned addition
- Mul
- Params: REG1, REG2
REG1 = REG1 * REG2- Unsigned multiplication
- Div
- Params: REG1, REG2
REG1 = REG1 / REG2- Unsigned division
- Mod
- Params: REG1, REG2
REG1 = REG1 % REG2(exact semantics TBD)
- INeg
- Params: REG1
REG1 = REG1 * -1- Signed negative
- And
- Params: REG1, REG2
REG1 = REG1 & REG2
- Or
- Params: REG1, REG2
REG1 = REG1 | REG2
- Inv
- Params: REG1
REG1 = ~REG1
- Not
- Params: REG1
-
* Boolean NOT; equivalent of C's `!` unary operator - Xor
- Params: REG1, REG2
REG1 = REG1 ^ REG2
- Shl
- Params: REG1, REG2
REG1 = REG1 << REG2
- Shr
- Params: REG1, REG2
REG1 = REG1 >> REG2- Does not sign extend
TODO
- Add signed instructions (iadd, imul, etc)
- Sign-extending SHR
- Overflow flag?
Control flow
- CmpEq
- Params: REG1, REG2
-
if REG1 == REG2 { FLAGS[1] = 1; } else { FLAGS[1] = 0; }
* Sets the COMPARE flag to 1 if REG1 == REG2 - CmpLt
- Params: REG1, REG2
-
if REG1 < REG2 { FLAGS[1] = 1; } else { FLAGS[1] = 0; }
* Sets the COMPARE flag to 1 if REG1 < REG2 - Jz
- Params: REG1
-
if FLAGS[1] == 0 { IP = REG1; }
* Jumps to the address in REG1 if COMPARE flag is 0. - Jnz
- Params: REG1
-
if FLAGS[1] != 0 { IP = REG1; }
* Jumps to the address in REG1 if COMPARE flag is 1.
Data movement
- Load
- Params: REG1, REG2
-
* Sets REG1 to the value at the memory address in REG2. - Store
- Params: REG1, REG2
-
* Sets the value at the memory address in REG2 to the value in REG1. - StoreImm32
- Params: REG1, IMM_32
REG1 = IMM_32- Sets REG1 to the specified 32-bit number.
- MemCopy
- Params: REG1, REG2
MEM[REG1] = MEM[REG2]- Copies the value at the memory address in REG2 to the memory address in REG1.
- RegCopy
- Params: REG1, REG2
REG1 = REG2- Copies the value in REG2 into REG1.
Miscellaneous
- Halt
- Params: (none)
FLAGS[0] = 1- Halts the machine
- Nop
- Params: (none)
- Does nothing
Other instructions TODO
- Call
- Takes address and number of bytes on the stack that are for args(?)
- Updates SP, FP, IP, storing previous values starting at the new FP
- Ret
- Uses FP to determine previous SP, FP, and IP and restores them
- Push
- Pop
- More immediate stores?
General TODO
- Interrupts
- MMIO regions
- Execution pipeline
- Helps to define when certain side effects happen (e.g. when the IP increments)
- Paging?