From 24d638c2695287e9f302808807a65c7418c6a611 Mon Sep 17 00:00:00 2001 From: Kevin Ramharak Date: Sun, 13 Jan 2019 12:35:50 +0100 Subject: [PATCH] change sorting to alphabetically for instructions --- Instruction-Set.md | 1007 ++++++++++++++++++++++---------------------- 1 file changed, 510 insertions(+), 497 deletions(-) diff --git a/Instruction-Set.md b/Instruction-Set.md index 600d46c..14c2c57 100644 --- a/Instruction-Set.md +++ b/Instruction-Set.md @@ -1,7 +1,5 @@ # Instruction set -The [instruction table](#instruction-table-with-affected-flags) is sorted alphabetically. - -The [instructions section](#instructions) is sorted numerically (on opcode). +The [instruction table](#instruction-table-with-affected-flags) and [instructions][#instructions] are sorted alphabetically. ### Instruction table with affected flags | Instruction mnemonic | Operands | Opcode | `C Z S O B` | @@ -90,30 +88,6 @@ Some instructions will change certain flags based on their result. These are in ## Instructions -### BRK -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `BRK` | `0x00` | | `-` | `-` | `-` | `-` | `1` | - -#### Description -`BRK` sets the break flag. This will halt execution until the next game 'tick', where it will be cleared and execution resumes from the start of the `.text` label. - -### MOV -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `MOV destination, source` | `0x01` | `destination` : `reg` / `mem` | `-` | `-` | `-` | `-` | `-` | -| | | `source` : `reg` / `mem` / `imm` | - -#### Description -`MOV` transfers (copies) a word from the source operand to the destination operand. - -#### Pseudo code -```py -destination = source -``` - ### ADD #### Details | mnemonic | opcode | operands | carry | zero | sign | overflow | break | @@ -129,21 +103,6 @@ destination = source destination = destination + source ``` -### SUB -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `SUB destination, source` | `0x03` | `destination` : `reg` / `mem` | `X` | `X` | `X` | `X` | `-` | -| | | `source` : `reg` / `mem` / `imm` | - -#### Description -`SUB` subtracts the source operand from the destination operand and stores the result in destination. - -#### Pseudo code -```py -destination = destination - source -``` - ### AND #### Details | mnemonic | opcode | operands | carry | zero | sign | overflow | break | @@ -162,108 +121,31 @@ destination = destination - source destination = destination & source ``` -### OR +### BRK #### Details | mnemonic | opcode | operands | carry | zero | sign | overflow | break | | -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `OR destination, source` | `0x05` | `destination` : `reg` / `mem` | `0` | `X` | `X` | `0` | `-` | -| | | `source` : `reg` / `mem` / `imm` | +| `BRK` | `0x00` | | `-` | `-` | `-` | `-` | `1` | #### Description -`OR` performs a bit-by-bit logical inclusive OR operation on its - operands and returns the result to destination. `OR` sets each bit - of the result to one if either or both of the corresponding bits - of the operands are one. - -#### Pseudo code -```py -destination = destination | source -``` - -### SAL -alias to [SHL](#shl) - -### SHL -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `SHL destination, count` | `0x06` | `destination` : `reg` / `mem` | `X` | `X` | `X` | `X` | `-` | -| | | `count` : `reg` / `mem` / `imm` | - -#### Description -`SHL` (Shift Logical Left) shifts the bits of the destination operand upward (toward the - most significant bit) by the number of bit positions specified in - the second operand (`count`). As bits are transferred out of the - left (high-order) end of the destination, zero bits are shifted - into the right (low-order) end. - -The carry flag (CF) is set equal to the last bit shifted out of the left end. - -#### Pseudo code -```py -destination = destination << count -#NOTE: be aware of the difference between a logical and an arithmetic shift -``` - -### SHR -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `SHR destination, count` | `0x07` | `destination` : `reg` / `mem` | `X` | `-` | `-` | `X` | `-` | -| | | `count` : `reg` / `mem` / `imm` | - -#### Description -`SHR` (Shift Logical Right) shifts the bits of the destination operand downward (toward - the least significant bit) by the number of bit positions - specified in the second operand (`count`). As bits are transferred - out of the right (low-order) end of the destination, zero bits are - shifted into the left (high-order) end. - -#### Pseudo code -```py -destination = destination >> count -#NOTE: be aware of the difference between a logical and an arithmetic shift -``` - -### HWI -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `HWI source` | `0x09` | `source` : `reg` / `mem` / `imm` | `-` | `-` | `-` | `-` | `-` | - -#### Description -`HWI` triggers a [Hardware Interrupt](https://github.com/simon987/Much-Assembly-Required/wiki/Hardware). `source` should be the address of the hardware device. This is different from the RAM memory addresses. See the documentation of the hardware devices to see what an `HWI` does for each device. - -### JMP -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `JMP target` | `0x0A` | `target` : `reg` / `mem` / `imm` | `-` | `-` | `-` | `-` | `-` | - -#### Description -`JMP` performs an unconditional jump to the target memory address and will resume execution there. +`BRK` sets the break flag. This will halt execution until the next game 'tick', where it will be cleared and execution resumes from the start of the `.text` label. + +### CALL +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `CALL target` | `0x15` | `target` : `reg` / `mem` / `imm` | `-` | `-` | `-` | `-` | `-` | + +#### Description +`CALL` pushes the current instruction pointer on to the stack and then performs a jump to the `target` address #### Pseudo code ```py +SP = SP - 1 +memory[SP] = IP IP = target ``` -### TEST -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `TEST destination, source` | `0x0B` | `destination` : `reg` / `mem` | `0` | `X` | `X` | `0` | `-` | -| | | `source` : `reg` / `mem` / `imm` | - -#### Description -`TEST` performs a bitwise AND operation on its two operands and - updates the flags. None of the operands are changed. - -#### Pseudo code -```py -destination & source # flags will be set -``` - ### CMP #### Details | mnemonic | opcode | operands | carry | zero | sign | overflow | break | @@ -281,33 +163,112 @@ destination & source # flags will be set destination - source # flags will be set ``` -### JNZ +### DEC #### Details | mnemonic | opcode | operands | carry | zero | sign | overflow | break | | -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `JNZ target` | `0x0D` | `target` : `reg` / `mem` / `imm` | `-` | `-` | `-` | `-` | `-` | - +| `DEC destination` | `0x2B` | `destination` : `mem` / `reg` | `-` | `X` | `X` | `X` | `-` | #### Description -`JNZ` performs a jump if the zero flag **IS NOT** set. +`DEC` subtracts one from the value of destination, replacing the previous value. Unlike [**SUB**](#sub) the carry flag is not modified. If you wish the carry flag to be modified then use `sub dest, 1` instead -#### Pseudo code +### Pseudo code ```py -if ZERO_FLAG == 0: - IP = target +destination = destination - 1 ``` -### JZ +### DIV #### Details | mnemonic | opcode | operands | carry | zero | sign | overflow | break | | -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `JZ target` | `0x0E` | `target` : `reg` / `mem` / `imm` | `-` | `-` | `-` | `-` | `-` | +| `DIV source` | `0x18` | `source` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `X` | #### Description -`JZ` performs a jump if the the zero flag **IS** set. +`DIV` performs unsigned division on `Y:A` with `source` as divisor and stores the result into `A` and the remainder in `Y`. + +> NOTE: `DIV` operates on a 32 bit integer composed of `Y:A`. So multiple `DIV` instructions without setting Y to what you want will result into unexpected results + +> NOTE: that a division by 0 will set the (undocumented) error flag and the break flag. This will halt execution. + +> This is a somewhat complicated instruction, +> see the [source](https://github.com/simon987/Much-Assembly-Required/blob/master/Server/source/main/java/net/simon987/server/assembly/instruction/DivInstruction.java) if needed + #### Pseudo code ```py -if ZERO_FLAG == 1: +if source == 0: + ERROR_FLAG = 1 + BREAK_FLAG = 1 + +# temp is a 32-bit integer +temp = (Y << 16) | A + +A = temp / source # result is floored +Y = temp % source +``` + +### HWI +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `HWI source` | `0x09` | `source` : `reg` / `mem` / `imm` | `-` | `-` | `-` | `-` | `-` | + +#### Description +`HWI` triggers a [Hardware Interrupt](https://github.com/simon987/Much-Assembly-Required/wiki/Hardware). `source` should be the address of the hardware device. This is different from the RAM memory addresses. See the documentation of the hardware devices to see what an `HWI` does for each device. + +### HWQ +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `HWQ source` | `0x1C` | `source` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `-` | + +#### Description +`HWQ` queries the hardware id of the hardware at the hardware address specified by `source` + +#### Pseudo code +```py +if hardware_memory[source] != None: + B = get_hardware_id( + hardware_memory[source] + ) +else: + B = 0 +``` + +### INC +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `INC destination` | `0x2A` | `destination` : `mem` / `reg` | `-` | `X` | `X` | `X` | `-` | +#### Description +`INC` adds one to the value of destination, replacing the previous value. Unlike [**ADD**](#add) the carry flag is not modified. If you wish the carry flag to be modified then use `add dest, 1` instead + +### Pseudo code +```py +destination = destination + 1 +``` + +### JA +#### Details + +#### Description + +#### Pseudo code +```py + +``` + +### JC +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `JC target` | `0x21` | `target` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `-` | + +#### Description +`JC` jumps to the `target` if the carry flag **IS** set. + +#### Pseudo code +```py +if CARRY_FLAG == 1: IP = target ``` @@ -371,72 +332,149 @@ if SIGN_FLAG != OVERFLOW_FLAG or ZERO_FLAG == 1: IP = target ``` -### PUSH +### JMP #### Details | mnemonic | opcode | operands | carry | zero | sign | overflow | break | | -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `PUSH source` | `0x13` | `source` : `reg` / `mem` / `imm` | `-` | `-` | `-` | `-` | `-` | +| `JMP target` | `0x0A` | `target` : `reg` / `mem` / `imm` | `-` | `-` | `-` | `-` | `-` | #### Description -`PUSH` decrements the stack pointer by one and then copies `source` to the address the stack pointer is pointing to. -> The stack grows downwards from 0xFFFF -> 0x0000 -> So decrementing will 'grow' the stack +`JMP` performs an unconditional jump to the target memory address and will resume execution there. #### Pseudo code ```py -SP = SP - 1 -memory[SP] = source -``` - -### POP -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `POP destination` | `0x14` | `destination` : `reg` / `mem` | `-` | `-` | `-` | `-` | `-` | - -#### Description -`POP` copies the value of the memory address specified in the stack pointer to the `destination` and increments the stack pointer. -> The stack grows downwards from 0xFFFF -> 0x0000 -> So incrementing will 'shrink' the stack - -#### Pseudo code -```py -destination = memory[SP] -SP = SP + 1 -``` - -### CALL -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `CALL target` | `0x15` | `target` : `reg` / `mem` / `imm` | `-` | `-` | `-` | `-` | `-` | - -#### Description -`CALL` pushes the current instruction pointer on to the stack and then performs a jump to the `target` address - -#### Pseudo code -```py -SP = SP - 1 -memory[SP] = IP IP = target ``` -### RET +### JNA #### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `RET [amount]` | `0x16` | `amount` : `imm` / `None` | `-` | `-` | `-` | `-` | `-` | #### Description -`RET` jumps to the address stored at the stack pointer and then increments (pops) that address of the stack. -When `amount` is given increment the stack pointer the number of times given in amount. #### Pseudo code ```py -IP = memory[SP] -if amount == None: - amount = 0 -SP = SP + 1 + amount + +``` + +### JNC +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `JNC target` | `0x22` | `target` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `-` | + +#### Description +`JNC` jumps to the `target` if the carry flag **IS NOT** set. + +#### Pseudo code +```py +if CARRY_FLAG == 0: + IP = target +``` + +### JNO +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `JNO target` | `0x25` | `target` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `-` | + +#### Description +`JNO` jumps to the `target` if the overflow flag **IS NOT** set. + +#### Pseudo code +```py +if OVERFLOW_FLAG == 0: + IP = target +``` + +### JNS +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `JNS target` | `0x1B` | `target` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `-` | + +#### Description +`JNS` jumps to the `target` if the sign flag **IS NOT** set. + +#### Pseudo code +```py +if SIGN_FLAG == 0: + IP = target +``` + + +### JNZ +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `JNZ target` | `0x0D` | `target` : `reg` / `mem` / `imm` | `-` | `-` | `-` | `-` | `-` | + +#### Description +`JNZ` performs a jump if the zero flag **IS NOT** set. + +#### Pseudo code +```py +if ZERO_FLAG == 0: + IP = target +``` + +### JO +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `JO target` | `0x24` | `target` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `-` | + +#### Description +`JO` jumps to the `target` if the overflow flag **IS** set. + +#### Pseudo code +```py +if OVERFLOW_FLAG == 1: + IP = target +``` + +### JS +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `JS target` | `0x1A` | `target` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `-` | + +#### Description +`JS` jumps to the `target` if the sign flag **IS** set. + +#### Pseudo code +```py +if SIGN_FLAG == 1: + IP = target +``` + +### JZ +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `JZ target` | `0x0E` | `target` : `reg` / `mem` / `imm` | `-` | `-` | `-` | `-` | `-` | + +#### Description +`JZ` performs a jump if the the zero flag **IS** set. + +#### Pseudo code +```py +if ZERO_FLAG == 1: + IP = target +``` + +### MOV +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `MOV destination, source` | `0x01` | `destination` : `reg` / `mem` | `-` | `-` | `-` | `-` | `-` | +| | | `source` : `reg` / `mem` / `imm` | + +#### Description +`MOV` transfers (copies) a word from the source operand to the destination operand. + +#### Pseudo code +```py +destination = source ``` ### MUL @@ -476,38 +514,6 @@ A = (result & 0x00ff) # you can check if you need Y by check the flags ``` -### DIV -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `DIV source` | `0x18` | `source` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `X` | - -#### Description -`DIV` performs unsigned division on `Y:A` with `source` as divisor and stores the result into `A` and the remainder in `Y`. - -> NOTE: `DIV` operates on a 32 bit integer composed of `Y:A`. So multiple `DIV` instructions without setting Y to what you want will result into unexpected results - -> NOTE: that a division by 0 will set the (undocumented) error flag and the break flag. This will halt execution. - -> This is a somewhat complicated instruction, -> see the [source](https://github.com/simon987/Much-Assembly-Required/blob/master/Server/source/main/java/net/simon987/server/assembly/instruction/DivInstruction.java) if needed - - -#### Pseudo code -```py - -if source == 0: - ERROR_FLAG = 1 - BREAK_FLAG = 1 - -# temp is a 32-bit integer -temp = (Y << 16) | A - -A = temp / source # result is floored -Y = temp % source - -``` - ### NEG #### Details | mnemonic | opcode | operands | carry | zero | sign | overflow | break | @@ -535,54 +541,18 @@ else destination = 0 - destination # or destination = destination + (-dest) ``` -### JS +### NOP #### Details | mnemonic | opcode | operands | carry | zero | sign | overflow | break | | -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `JS target` | `0x1A` | `target` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `-` | +| `NOP` | `0x3F` | | `-` | `-` | `-` | `-` | `-` | -#### Description -`JS` jumps to the `target` if the sign flag **IS** set. +### Description +`NOP` is an instruction that performs no operation. Often used for timing purposes, as a placeholder or for aligning purposes. -#### Pseudo code +### Pseudo code ```py -if SIGN_FLAG == 1: - IP = target -``` - -### JNS -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `JNS target` | `0x1B` | `target` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `-` | - -#### Description -`JNS` jumps to the `target` if the sign flag **IS NOT** set. - -#### Pseudo code -```py -if SIGN_FLAG == 0: - IP = target -``` - -### HWQ -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `HWQ source` | `0x1C` | `source` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `-` | - -#### Description -`HWQ` queries the hardware id of the hardware at the hardware address specified by `source` - -#### Pseudo code -```py -if hardware_memory[source] != None: - # not sure how to (pseudo) code this - B = get_hardware_id( - hardware_memory[source] - ) -else: - B = 0 +# do nothing ``` ### NOT @@ -599,184 +569,102 @@ else: dest = ~dest ``` -### XCHG +### OR #### Details | mnemonic | opcode | operands | carry | zero | sign | overflow | break | | -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `XCHG destination, source` | `0x1F` | `destination` : `mem` / `reg` | `-` | `-` | `-` | `-` | `-` | -| | | `source` : `mem` / `reg` | - -#### Description -`XCHG` switches the contents of two operands. - -#### Pseudo code -```py -temp = destination -destination = source -source = temp -``` - -### ROR -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `ROR destination, count` | `0x20` | `destination` : `mem` / `reg` | `X` | `-` | `-` | `X` | `-` | -| | | `count` : `mem` / `reg`, `imm` | - -#### Description -`ROR` shifts the bits of `destination` operand to the right by the number of bit positions specified by `count`. - -if `count` is greater than 15 it will be the remainder of a division by 16. - -as bits are transferred out the right (low-order) end of the destination, they re-enter on the left (high-order) end. The carry flag (CF) is updated to match the last bit shifted out of the right end. - -if `count` equals 1 then the overflow flag will be set if the sign bit of `destination` has changed - -#### Pseudo code -```py -count = count % 16 - -# TODO: less implementation more pseudo code -if (destination & 0x8000) > 0: # check if sign bit was set - old_sign_bit = 1 -else - old_sign_bit = 0 - -destination = #... ROR magic - -if (destination & 0x8000) > 0: # check if sign bit was set - new_sign_bit = 1 -else - new_sign_bit = 0 - -if count == 1: - OVERFLOW_FLAG = (old_signbit != new_signbit) # check if sign bit changed - -if new_sign_bit == 1: - CARRY_FLAG = 1 -else: - CARRY_FLAG = 0 -``` - -### JC -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `JC target` | `0x21` | `target` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `-` | - -#### Description -`JC` jumps to the `target` if the carry flag **IS** set. - -#### Pseudo code -```py -if CARRY_FLAG == 1: - IP = target -``` - -### JNC -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `JNC target` | `0x22` | `target` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `-` | - -#### Description -`JNC` jumps to the `target` if the carry flag **IS NOT** set. - -#### Pseudo code -```py -if CARRY_FLAG == 0: - IP = target -``` - -### ROL -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `ROL destination, count` | `0x23` | `destination` : `mem` / `reg` | `X` | `-` | `-` | `X` | `-` | -| | | `count` : `mem` / `reg`, `imm` | - -#### Description -`ROL` shifts the bits of `destination` operand to the left by the number of bit positions specified by `count`. - -if `count` is greater than 15 it will be the remainder of a division by 16. - -as bits are transferred out the left (high-order) end of the destination, they re-enter on the right (low-order) end. The carry flag (CF) is updated to match the last bit shifted out of the left end. - -if `count` equals 1 then the overflow flag will be set if the sign bit of `destination` has changed - -#### Pseudo code -```py -count = count % 16 - -# TODO: less implementation more pseudo code -if (destination & 0x8000) > 0: # check if sign bit was set - old_sign_bit = 1 -else - old_sign_bit = 0 - -destination = #... ROL magic - -# carry flag might be set - -if (destination & 0x8000) > 0: # check if sign bit was set - new_sign_bit = 1 -else - new_sign_bit = 0 - -if count == 1: - OVERFLOW_FLAG = (old_signbit != new_signbit) # check if sign bit changed - -# TODO: less implementation more pseudo code -if (destination & 0x01) == 1: - CARRY_FLAG = 1 -else: - CARRY_FLAG = 0 -``` - -### JO -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `JO target` | `0x24` | `target` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `-` | - -#### Description -`JO` jumps to the `target` if the overflow flag **IS** set. - -#### Pseudo code -```py -if OVERFLOW_FLAG == 1: - IP = target -``` - -### JNO -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `JNO target` | `0x25` | `target` : `mem` / `reg` / `imm` | `-` | `-` | `-` | `-` | `-` | - -#### Description -`JNO` jumps to the `target` if the overflow flag **IS NOT** set. - -#### Pseudo code -```py -if OVERFLOW_FLAG == 0: - IP = target -``` - -### XOR -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `XOR destination, source` | `0x26` | `destination` : `reg` / `mem` | `0` | `X` | `X` | `0` | `-` | +| `OR destination, source` | `0x05` | `destination` : `reg` / `mem` | `0` | `X` | `X` | `0` | `-` | | | | `source` : `reg` / `mem` / `imm` | #### Description -XOR performs a bit-by-bit "exclusive or" on its two operands, and - returns the result in the destination operand. XOR sets each bit - of the result to one if only one of the corresponding bits is set - to one. +`OR` performs a bit-by-bit logical inclusive OR operation on its + operands and returns the result to destination. `OR` sets each bit + of the result to one if either or both of the corresponding bits + of the operands are one. #### Pseudo code ```py -destination = destination ^ source +destination = destination | source +``` + +### POP +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `POP destination` | `0x14` | `destination` : `reg` / `mem` | `-` | `-` | `-` | `-` | `-` | + +#### Description +`POP` copies the value of the memory address specified in the stack pointer to the `destination` and increments the stack pointer. +> The stack grows downwards from 0xFFFF -> 0x0000 +> So incrementing will 'shrink' the stack + +#### Pseudo code +```py +destination = memory[SP] +SP = SP + 1 +``` + + +### POPF +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `POPF` | `0x2C` | | `X` | `X` | `X` | `X` | `-` | + +#### Description +Pops a word of the top of the stack and uses the 4 lowest bits of the result to set the CPU flags. In the order *sign*, *zero*, *carry* and *overflow* also represented by the following bit pattern `xxxx xxxx xxxx SZCO`. + +All flags will be according to the corresponding bit values of given word. To only set on flag a `PUSHF` to query the flags and a bitmask with the desired flag to manipulate should be used. + +#### Pseudo code +```py +flags = memory[SP] + +SIGN_FLAG = flags & (1 << 3) +ZERO_FLAG = flags & (1 << 2) +CARRY_FLAG = flags & (1 << 1) +OVERFLOW_FLAG = flags & 1 + +SP = SP + 1 +``` + +### PUSH +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `PUSH source` | `0x13` | `source` : `reg` / `mem` / `imm` | `-` | `-` | `-` | `-` | `-` | + +#### Description +`PUSH` decrements the stack pointer by one and then copies `source` to the address the stack pointer is pointing to. +> The stack grows downwards from 0xFFFF -> 0x0000 +> So decrementing will 'grow' the stack + +#### Pseudo code +```py +SP = SP - 1 +memory[SP] = source +``` + +### PUSHF +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `PUSHF` | `0x2D` | | `-` | `-` | `-` | `-` | `-` | + +#### Description +Pushes the current flags on top of the stack. The flags are present in the 4 lowest bits of the result on the stack. In the order *sign*, *zero*, *carry* and *overflow* also represented by the following bit pattern `xxxx xxxx xxxx SZCO`. + +To get the state of a single flag you can use a bit mask. + +example: the operation `flags & 0100` will give a result of 1 if the zero flag was set and a result of 0 if it was unset + +#### Pseudo code +```py +# 0000 0000 0000 SZCO +flags = (SIGN_FLAG << 3) | (ZERO_FLAG << 2) | (CARRY_FLAG << 1) | (OVERFLOW_FLAG) + +SP = SP - 1 +memory[SP] = flags ``` ### RCL @@ -856,7 +744,7 @@ if (destination & 0x8000) > 0: else old_sign_bit = 0 -destination = # ... RCL magic +destination = # ... RCR magic # carry flag might be set @@ -869,6 +757,112 @@ if count == 1: OVERFLOW_FLAG = (old_sign_bit != new_sign_bit) ``` +### RET +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `RET [amount]` | `0x16` | `amount` : `imm` / `None` | `-` | `-` | `-` | `-` | `-` | + +#### Description +`RET` jumps to the address stored at the stack pointer and then increments (pops) that address of the stack. +When `amount` is given increment the stack pointer the number of times given in amount. + +#### Pseudo code +```py +IP = memory[SP] +if amount == None: + amount = 0 +SP = SP + 1 + amount +``` + +### ROL +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `ROL destination, count` | `0x23` | `destination` : `mem` / `reg` | `X` | `-` | `-` | `X` | `-` | +| | | `count` : `mem` / `reg`, `imm` | + +#### Description +`ROL` shifts the bits of `destination` operand to the left by the number of bit positions specified by `count`. + +if `count` is greater than 15 it will be the remainder of a division by 16. + +as bits are transferred out the left (high-order) end of the destination, they re-enter on the right (low-order) end. The carry flag (CF) is updated to match the last bit shifted out of the left end. + +if `count` equals 1 then the overflow flag will be set if the sign bit of `destination` has changed + +#### Pseudo code +```py +count = count % 16 + +# TODO: less implementation more pseudo code +if (destination & 0x8000) > 0: # check if sign bit was set + old_sign_bit = 1 +else + old_sign_bit = 0 + +destination = #... ROL magic + +# carry flag might be set + +if (destination & 0x8000) > 0: # check if sign bit was set + new_sign_bit = 1 +else + new_sign_bit = 0 + +if count == 1: + OVERFLOW_FLAG = (old_signbit != new_signbit) # check if sign bit changed + +# TODO: less implementation more pseudo code +if (destination & 0x01) == 1: + CARRY_FLAG = 1 +else: + CARRY_FLAG = 0 +``` + +### ROR +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `ROR destination, count` | `0x20` | `destination` : `mem` / `reg` | `X` | `-` | `-` | `X` | `-` | +| | | `count` : `mem` / `reg`, `imm` | + +#### Description +`ROR` shifts the bits of `destination` operand to the right by the number of bit positions specified by `count`. + +if `count` is greater than 15 it will be the remainder of a division by 16. + +as bits are transferred out the right (low-order) end of the destination, they re-enter on the left (high-order) end. The carry flag (CF) is updated to match the last bit shifted out of the right end. + +if `count` equals 1 then the overflow flag will be set if the sign bit of `destination` has changed + +#### Pseudo code +```py +count = count % 16 + +# TODO: less implementation more pseudo code +if (destination & 0x8000) > 0: # check if sign bit was set + old_sign_bit = 1 +else + old_sign_bit = 0 + +destination = #... ROR magic + +if (destination & 0x8000) > 0: # check if sign bit was set + new_sign_bit = 1 +else + new_sign_bit = 0 + +if count == 1: + OVERFLOW_FLAG = (old_signbit != new_signbit) # check if sign bit changed + +if new_sign_bit == 1: + CARRY_FLAG = 1 +else: + CARRY_FLAG = 0 +``` + +### SAL +alias to [SHL](#shl) + ### SAR #### Details | mnemonic | opcode | operands | carry | zero | sign | overflow | break | @@ -890,93 +884,112 @@ destination = destination <<< count #NOTE: be aware of the difference between a logical and an arithmetic shift ``` -### INC +### SHL #### Details | mnemonic | opcode | operands | carry | zero | sign | overflow | break | | -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `INC destination` | `0x2A` | `destination` : `mem` / `reg` | `-` | `X` | `X` | `X` | `-` | -#### Description -`INC` adds one to the value of destination, replacing the previous value. Unlike [**ADD**](#add) the carry flag is not modified. If you wish the carry flag to be modified then use `add dest, 1` instead - -### Pseudo code -```py -destination = destination + 1 -``` - -### DEC -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `DEC destination` | `0x2B` | `destination` : `mem` / `reg` | `-` | `X` | `X` | `X` | `-` | -#### Description -`DEC` subtracts one from the value of destination, replacing the previous value. Unlike [**SUB**](#sub) the carry flag is not modified. If you wish the carry flag to be modified then use `sub dest, 1` instead - -### Pseudo code -```py -destination = destination - 1 -``` - -### POPF -#### Details -| mnemonic | opcode | operands | carry | zero | sign | overflow | break | -| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `POPF` | `0x2C` | | `X` | `X` | `X` | `X` | `-` | +| `SHL destination, count` | `0x06` | `destination` : `reg` / `mem` | `X` | `X` | `X` | `X` | `-` | +| | | `count` : `reg` / `mem` / `imm` | #### Description -Pops a word of the top of the stack and uses the 4 lowest bits of the result to set the CPU flags. In the order *sign*, *zero*, *carry* and *overflow* also represented by the following bit pattern `xxxx xxxx xxxx SZCO`. +`SHL` (Shift Logical Left) shifts the bits of the destination operand upward (toward the + most significant bit) by the number of bit positions specified in + the second operand (`count`). As bits are transferred out of the + left (high-order) end of the destination, zero bits are shifted + into the right (low-order) end. -All flags will be according to the corresponding bit values of given word. To only set on flag a `PUSHF` to query the flags and a bitmask with the desired flag to manipulate should be used. +The carry flag (CF) is set equal to the last bit shifted out of the left end. #### Pseudo code ```py -flags = memory[SP] - -SIGN_FLAG = flags & (1 << 3) -ZERO_FLAG = flags & (1 << 2) -CARRY_FLAG = flags & (1 << 1) -OVERFLOW_FLAG = flags & 1 - -SP = SP + 1 +destination = destination << count +#NOTE: be aware of the difference between a logical and an arithmetic shift ``` -### PUSHF +### SHR #### Details | mnemonic | opcode | operands | carry | zero | sign | overflow | break | | -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `PUSHF` | `0x2D` | | `-` | `-` | `-` | `-` | `-` | +| `SHR destination, count` | `0x07` | `destination` : `reg` / `mem` | `X` | `-` | `-` | `X` | `-` | +| | | `count` : `reg` / `mem` / `imm` | #### Description -Pushes the current flags on top of the stack. The flags are present in the 4 lowest bits of the result on the stack. In the order *sign*, *zero*, *carry* and *overflow* also represented by the following bit pattern `xxxx xxxx xxxx SZCO`. - -To get the state of a single flag you can use a bit mask. - -example: the operation `flags & 0100` will give a result of 1 if the zero flag was set and a result of 0 if it was unset +`SHR` (Shift Logical Right) shifts the bits of the destination operand downward (toward + the least significant bit) by the number of bit positions + specified in the second operand (`count`). As bits are transferred + out of the right (low-order) end of the destination, zero bits are + shifted into the left (high-order) end. #### Pseudo code ```py -# 0000 0000 0000 SZCO -flags = (SIGN_FLAG << 3) | (ZERO_FLAG << 2) | (CARRY_FLAG << 1) | (OVERFLOW_FLAG) - -SP = SP - 1 -memory[SP] = flags +destination = destination >> count +#NOTE: be aware of the difference between a logical and an arithmetic shift ``` -### JA - -### JNA - -### NOP +### SUB #### Details | mnemonic | opcode | operands | carry | zero | sign | overflow | break | | -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | -| `NOP` | `0x3F` | | `-` | `-` | `-` | `-` | `-` | +| `SUB destination, source` | `0x03` | `destination` : `reg` / `mem` | `X` | `X` | `X` | `X` | `-` | +| | | `source` : `reg` / `mem` / `imm` | -### Description -`NOP` is an instruction that performs no operation. Often used for timing purposes, as a placeholder or for aligning purposes. +#### Description +`SUB` subtracts the source operand from the destination operand and stores the result in destination. -### Pseudo code +#### Pseudo code ```py -# do nothing +destination = destination - source +``` + +### TEST +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `TEST destination, source` | `0x0B` | `destination` : `reg` / `mem` | `0` | `X` | `X` | `0` | `-` | +| | | `source` : `reg` / `mem` / `imm` | + +#### Description +`TEST` performs a bitwise AND operation on its two operands and + updates the flags. None of the operands are changed. + +#### Pseudo code +```py +destination & source # flags will be set +``` + +### XCHG +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `XCHG destination, source` | `0x1F` | `destination` : `mem` / `reg` | `-` | `-` | `-` | `-` | `-` | +| | | `source` : `mem` / `reg` | + +#### Description +`XCHG` switches the contents of two operands. + +#### Pseudo code +```py +temp = destination +destination = source +source = temp +``` + +### XOR +#### Details +| mnemonic | opcode | operands | carry | zero | sign | overflow | break | +| -------- | ------ | -------- | ----- | ---- | ---- | -------- | ----- | +| `XOR destination, source` | `0x26` | `destination` : `reg` / `mem` | `0` | `X` | `X` | `0` | `-` | +| | | `source` : `reg` / `mem` / `imm` | + +#### Description +XOR performs a bit-by-bit "exclusive or" on its two operands, and + returns the result in the destination operand. XOR sets each bit + of the result to one if only one of the corresponding bits is set + to one. + +#### Pseudo code +```py +destination = destination ^ source ``` ### Instruction encoding