Add opcodes and layout for most instructions

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-01-28 19:16:52 -05:00
parent 54f61101c6
commit 2148fed5a5

113
vm.md
View File

@@ -48,40 +48,52 @@ CPU flags are addressed by bit index, going from right to left.
# Instructions
Instructions attempt to be as small as possible while conforming to 8-bit, 16-bit, 32-bit, or 64-bit
alignment. All instructions have 16-bit opcodes.
## Arithmetic
Arithmetic instructions store their result in the first register specified. Overflow is handled by
wrapping around to 0.
* Add
* Opcode: 0x0000
* **Params**: REG1, REG2
* `REG1 = REG1 + REG2`
* Unsigned addition
* Mul
* Opcode: 0x0001
* **Params**: REG1, REG2
* `REG1 = REG1 * REG2`
* Unsigned multiplication
* Div
* Opcode: 0x0002
* **Params**: REG1, REG2
* `REG1 = REG1 / REG2`
* Unsigned division
* Mod
* Opcode: 0x0003
* **Params**: REG1, REG2
* `REG1 = REG1 % REG2` (exact semantics TBD)
* INeg
* Opcode: 0x0004
* **Params**: REG1
* `REG1 = REG1 * -1`
* Signed negative
* And
* Opcode: 0x0005
* **Params**: REG1, REG2
* `REG1 = REG1 & REG2`
* Or
* Opcode: 0x0006
* **Params**: REG1, REG2
* `REG1 = REG1 | REG2`
* Inv
* Opcode: 0x0007
* **Params**: REG1
* `REG1 = ~REG1`
* Not
* Opcode: 0x0008
* **Params**: REG1
* ```
if REG1 == 0 {
@@ -92,12 +104,15 @@ wrapping around to 0.
```
* Boolean NOT; equivalent of C's `!` unary operator
* Xor
* Opcode: 0x0009
* **Params**: REG1, REG2
* `REG1 = REG1 ^ REG2`
* Shl
* Opcode: 0x000A
* **Params**: REG1, REG2
* `REG1 = REG1 << REG2`
* Shr
* Opcode: 0x000B
* **Params**: REG1, REG2
* `REG1 = REG1 >> REG2`
* Does not sign extend
@@ -111,6 +126,7 @@ wrapping around to 0.
## Control flow
* CmpEq
* Opcode: 0x1000
* **Params**: REG1, REG2
* ```
if REG1 == REG2 {
@@ -121,6 +137,7 @@ wrapping around to 0.
```
* Sets the COMPARE flag to 1 if REG1 == REG2
* CmpLt
* Opcode: 0x1001
* **Params**: REG1, REG2
* ```
if REG1 < REG2 {
@@ -131,6 +148,7 @@ wrapping around to 0.
```
* Sets the COMPARE flag to 1 if REG1 < REG2
* Jz
* Opcode: 0x1100
* **Params**: REG1
* ```
if FLAGS[1] == 0 {
@@ -139,6 +157,7 @@ wrapping around to 0.
```
* Jumps to the address in REG1 if COMPARE flag is 0.
* Jnz
* Opcode: 0x1001
* **Params**: REG1
* ```
if FLAGS[1] != 0 {
@@ -150,39 +169,108 @@ wrapping around to 0.
## Data movement
* Load
* Opcode: 0x2000
* **Params**: REG1, REG2
* ```
REG1 = MEM[REG2];
```
* Sets REG1 to the value at the memory address in REG2.
* ```
32 16 10 4 0
64 - opcode reg1 reg2 unused
/ / / /
+-------------------------------------------+
| 0010000000000000 | ...... | ...... | XXXX |
+-------------------------------------------+
```
* RegCopy
* Opcode: 0x2001
* **Params**: REG1, REG2
* `REG1 = REG2`
* Copies the value in REG2 into REG1.
* ```
32 16 10 4 0
opcode reg1 reg2 unused
/ / / /
+-------------------------------------------+
| 0010000000000001 | REG1.. | REG2.. | XXXX |
+-------------------------------------------+
```
* StoreImm64
* Opcode: 0x2100
* **Params**: REG1, IMM_64
* `REG1 = IMM_64`
* Sets REG1 to the specified 64-bit number.
* StoreImm32
* Opcode: 0x2101
* **Params**: REG1, IMM_32
* `REG1 = IMM_32`
* Sets REG1 to the specified 32-bit number.
* ```
64 48 42 36 32 0
opcode reg1 reg2 unused
/ / / / immediate 32 bit value
/ / / / /
+------------------------------------------------------------------------------+
| 0010000100000001 | REG1.. | REG2.. | XXXX | IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII |
+------------------------------------------------------------------------------+
```
* MemCopy
* Opcode: 0x2200
* **Params**: REG1, REG2
* `MEM[REG1] = MEM[REG2]`
* Copies the value at the memory address in REG2 to the memory address in REG1.
* ```
32 16 10 4 0
opcode reg1 reg2 unused
/ / / /
+-------------------------------------------+
| 0010001000000000 | REG1.. | REG2.. | XXXX |
+-------------------------------------------+
```
* Store
* Opcode: 0x2201
* **Params**: REG1, REG2
* ```
MEM[REG2] = REG1;
```
* 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.
* ```
32 16 10 4 0
opcode reg1 reg2 unused
/ / / /
+-------------------------------------------+
| 0010001000000001 | REG1.. | REG2.. | XXXX |
+-------------------------------------------+
```
## Miscellaneous
* Halt
* Opcode: 0xF000
* **Params**: (none)
* `FLAGS[0] = 1`
* Halts the machine
* ```
16
opcode
/
+------------------+
| 0010011000000000 |
+------------------+
```
* Nop
* Opcode: 0xF001
* **Params**: (none)
* Does nothing
* ```
16
opcode
/
+------------------+
| 0010011000000001 |
+------------------+
```
## Other instructions TODO
@@ -194,6 +282,7 @@ wrapping around to 0.
* Push
* Pop
* More immediate stores?
* Idea: Store42 (or whatever number of bits) that maximizes the usage of a 64-bit instruction
# Binary object format