Add opcodes and layout for most instructions
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
113
vm.md
113
vm.md
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user