2020-01-25 19:17:39 -05:00
|
|
|
# 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.
|
|
|
|
|
|
|
|
|
|
| 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
|
|
|
|
|
* (10 unused registers)
|
|
|
|
|
* R0-R49
|
|
|
|
|
|
|
|
|
|
## CPU Flags
|
|
|
|
|
|
|
|
|
|
CPU flags are addressed by bit index, going from right to left.
|
|
|
|
|
|
|
|
|
|
* `00` - Halt flag
|
|
|
|
|
* `01` - 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 last register specified.
|
|
|
|
|
|
|
|
|
|
* Add
|
|
|
|
|
* **Params**: REG1, REG2
|
|
|
|
|
* `REG2 = REG1 + REG2`
|
|
|
|
|
* Mul
|
|
|
|
|
* **Params**: REG1, REG2
|
|
|
|
|
* `REG2 = REG1 * REG2`
|
|
|
|
|
* Div
|
|
|
|
|
* **Params**: REG1, REG2
|
|
|
|
|
* `REG2 = REG1 / REG2`
|
2020-01-25 21:06:43 -05:00
|
|
|
* Mod
|
|
|
|
|
* **Params**: REG1, REG2
|
|
|
|
|
* `REG2 = REG1 % REG2` (exact semantics TBD)
|
2020-01-25 19:17:39 -05:00
|
|
|
* Neg
|
|
|
|
|
* **Params**: REG1
|
|
|
|
|
* `REG1 = REG1 * -1`
|
|
|
|
|
* And
|
|
|
|
|
* **Params**: REG1, REG2
|
|
|
|
|
* `REG2 = REG1 & REG2`
|
|
|
|
|
* Or
|
|
|
|
|
* **Params**: REG1, REG2
|
|
|
|
|
* `REG2 = REG1 | REG2`
|
|
|
|
|
* Xor
|
|
|
|
|
* **Params**: REG1, REG2
|
|
|
|
|
* `REG2 = REG1 ^ REG2`
|
|
|
|
|
* Shl
|
|
|
|
|
* **Params**: REG1, REG2
|
|
|
|
|
* `REG1 = REG1 << REG2`
|
|
|
|
|
* Shr
|
|
|
|
|
* **Params**: REG1, REG2
|
|
|
|
|
* `REG1 = REG1 >> REG2`
|
|
|
|
|
|
|
|
|
|
## Control flow
|
|
|
|
|
|
|
|
|
|
* CmpEq
|
|
|
|
|
* **Params**: REG1, REG2
|
|
|
|
|
* ```
|
|
|
|
|
if REG1 == REG2 {
|
|
|
|
|
FLAGS[1] = 1;
|
|
|
|
|
} else {
|
|
|
|
|
FLAGS[1] = 0;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
* CmpLt
|
|
|
|
|
* **Params**: REG1, REG2
|
|
|
|
|
* ```
|
|
|
|
|
if REG1 < REG2 {
|
|
|
|
|
FLAGS[1] = 1;
|
|
|
|
|
} else {
|
|
|
|
|
FLAGS[1] = 0;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
* Jz
|
|
|
|
|
* **Params**: REG1
|
|
|
|
|
* ```
|
|
|
|
|
if FLAGS[0] == 0 {
|
|
|
|
|
IP = REG1;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
* Jnz
|
|
|
|
|
* **Params**: REG1
|
|
|
|
|
* ```
|
|
|
|
|
if FLAGS[0] != 0 {
|
|
|
|
|
IP = REG1;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Data movement
|
|
|
|
|
|
|
|
|
|
* Load
|
|
|
|
|
* **Params**: REG1, REG2
|
|
|
|
|
* ```
|
|
|
|
|
REG1 = MEM[REG2];
|
|
|
|
|
```
|
|
|
|
|
* Store
|
|
|
|
|
* **Params**: REG1, REG2
|
|
|
|
|
* ```
|
|
|
|
|
MEM[REG2] = REG1;
|
|
|
|
|
```
|
|
|
|
|
* StoreImm32
|
|
|
|
|
* (hw = half word)
|
|
|
|
|
* **Params**: REG1, IMM_HW
|
|
|
|
|
* `REG1 = IMM_HW`
|
2020-01-25 21:02:32 -05:00
|
|
|
* MemCopy
|
2020-01-25 19:17:39 -05:00
|
|
|
* **Params**: REG1, REG2
|
|
|
|
|
* `MEM[REG1] = MEM[REG2]`
|
2020-01-25 21:02:32 -05:00
|
|
|
* RegCopy
|
|
|
|
|
* **Params**: REG1, REG2
|
|
|
|
|
* `REG1 = REG2`
|