# 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. * Signed numbers use two's complement. | 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 first register specified. Overflow is handled by wrapping around to 0. * Add * **Params**: REG1, REG2 * `REG1 = REG1 + REG2` * Unsigned addition * Mul * **Params**: REG1, REG2 * `REG1 = REG1 * REG2` * Unsigned multiplication * Div * **Params**: REG1, REG2 * `REG1 = REG1 / REG2` * Unsigned division * Mod * **Params**: REG1, REG2 * `REG1 = REG1 % REG2` (exact semantics TBD) * INeg * **Params**: REG1 * `REG1 = REG1 * -1` * Signed negative * And * **Params**: REG1, REG2 * `REG1 = REG1 & REG2` * Or * **Params**: REG1, REG2 * `REG1 = REG1 | REG2` * Xor * **Params**: REG1, REG2 * `REG1 = REG1 ^ REG2` * Shl * **Params**: REG1, REG2 * `REG1 = REG1 << REG2` * Shr * **Params**: REG1, REG2 * `REG1 = REG1 >> REG2` ### TODO * Add signed instructions (iadd, imul, etc) * Overflow flag? ## 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 * **Params**: REG1, IMM_32 * `REG1 = IMM_32` * MemCopy * **Params**: REG1, REG2 * `MEM[REG1] = MEM[REG2]` * RegCopy * **Params**: REG1, REG2 * `REG1 = REG2`