## involution16

`involution16` is a 16 bit little-endian ISA where every instruction is an involution. An emulator and example programs are available here.

There are 16 instructions, with most being Toffoli gates extended to integer operations.

With the exception of `srr`, `srm`, and `brk`, only the first argument to an instruction will be modified. The register used as the first argument must never appear more than once in an instruction.

There are sixteen 16-bit registers, referred to as `r0` through `rF` (using hex).

The program counter will loop around to `0x0000` once reaching `0xFFFF`.

There are technically 65536 bytes of accessible memory, as a 2 byte read at `0xFFFF` will include the byte at `0x10000`.

### Arithmetic Instructions

``````0h | add c, a, b -> c ^= a + b
1h | sub c, a, b -> c ^= a - b
2h | ror c, a, b -> c ^= a >>> (b & 0xF)
3h | rol c, a, b -> c ^= a <<< (b & 0xF)
4h | shr c, a, b -> c ^= a >> (b & 0xF)
5h | shl c, a, b -> c ^= a << (b & 0xF)
6h | and c, a, b -> c ^= a & b
7h | ora c, a, b -> c ^= a | b
8h | mul c, a, b -> c ^= a * b
9h | div c, a, b -> c ^= (b == 0) ? 0 : (a / b)
``````

### Special Instructions

``````Ah | cmp flags, a, b -> flags ^= min(1, max(-1, a - b))
Bh | jeq c, a, b -> {
; Jump (if) EQual
; a, b = operands
if (a == b) {
; jump address must be aligned
assert(c % 2 == 0)
; the instruction at the jump address must be equal to the current
; instruction
assert(memcmp(pc, c, 2) == 0)

; swap pc and c
t = pc
pc = c
c = t
}
}
Ch | xri a, b -> a ^= SignExtend16(b)
; Xor Register (with) Immediate
; b is not a register, but an 8 bit immediate value
Dh | srr a, b -> {
; Swap Register (with) Register
t = a
a = b
b = t
}
Eh | srm a, b -> {
; Swap Register (with) Memory
t = a
a = *b
*b = t
}
Fh | brk
; Break - stop execution
``````

### Instruction Encoding

All instructions are 16 bits wide, split into 4 nibble-wide fields.

``````; cmp, jeq, and arithmetic instructions
insn & 0xF000 -> opcode
insn & 0x0F00 -> register argument 1
insn & 0x00F0 -> register argument 2
insn & 0x000F -> register argument 3
; xri
insn & 0xF000 -> opcode
insn & 0x0F00 -> register argument 1
insn & 0x00FF -> signed 8 bit immediate value
; srr and srm
insn & 0xF000 -> opcode
insn & 0x0F00 -> register argument 1
insn & 0x00F0 -> register argument 2
insn & 0x000F -> unused
; brk
insn & 0xF000 -> opcode
insn & 0x0FFF -> unused
``````