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