From 2148fed5a5975b76d22d88f006a3538ecffcd8f7 Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Tue, 28 Jan 2020 19:16:52 -0500 Subject: [PATCH] Add opcodes and layout for most instructions Signed-off-by: Alek Ratzloff --- vm.md | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 12 deletions(-) diff --git a/vm.md b/vm.md index 6328586..309894d 100644 --- a/vm.md +++ b/vm.md @@ -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