diff --git a/src/CPU_Instruction_Set.md b/src/CPU_Instruction_Set.md
index 3028d21f..7a14e6d7 100644
--- a/src/CPU_Instruction_Set.md
+++ b/src/CPU_Instruction_Set.md
@@ -1,151 +1,192 @@
# CPU Instruction Set
-Tables below specify the mnemonic, encoding, clock cycles, affected
-flags (ordered as znhc), and description. The timings assume a CPU
-clock frequency of 4.194304 MHz (or 8.4 MHz for CGB in double speed
-mode), called "T-states". Because all Game Boy timings are divisible
-by 4, many people specify timings and clock frequency divided by 4,
-called "M-cycles".
-
-## 8-bit Load instructions
-
-Mnemonic | Encoding | Clock cycles | Flags | Description
------------------|----------|--------------|-------|-------------
- ld r,r | xx | 4 | ---- | r=r
- ld r,n | xx nn | 8 | ---- | r=n
- ld r,(HL) | xx | 8 | ---- | r=(HL)
- ld (HL),r | 7x | 8 | ---- | (HL)=r
- ld (HL),n | 36 nn | 12 | ---- | (HL)=n
- ld A,(BC) | 0A | 8 | ---- | A=(BC)
- ld A,(DE) | 1A | 8 | ---- | A=(DE)
- ld A,(nn) | FA | 16 | ---- | A=(nn)
- ld (BC),A | 02 | 8 | ---- | (BC)=A
- ld (DE),A | 12 | 8 | ---- | (DE)=A
- ld (nn),A | EA | 16 | ---- | (nn)=A
- ld A,(FF00+n) | F0 nn | 12 | ---- | read from io-port n (memory FF00+n)
- ld (FF00+n),A | E0 nn | 12 | ---- | write to io-port n (memory FF00+n)
- ld A,(FF00+C) | F2 | 8 | ---- | read from io-port C (memory FF00+C)
- ld (FF00+C),A | E2 | 8 | ---- | write to io-port C (memory FF00+C)
- ldi (HL),A | 22 | 8 | ---- | (HL)=A, HL=HL+1
- ldi A,(HL) | 2A | 8 | ---- | A=(HL), HL=HL+1
- ldd (HL),A | 32 | 8 | ---- | (HL)=A, HL=HL-1
- ldd A,(HL) | 3A | 8 | ---- | A=(HL), HL=HL-1
-
-## 16-bit Load instructions
-
-Mnemonic | Encoding | Clock cycles | Flags | Description
------------------|----------|--------------|-------|-------------
- ld rr,nn | x1 nn nn | 12 | ---- | rr=nn (rr may be BC,DE,HL or SP)
- ld (nn),SP | 08 nn nn | 20 | ---- | (nn)=SP
- ld SP,HL | F9 | 8 | ---- | SP=HL
- push rr | x5 | 16 | ---- | SP=SP-2 (SP)=rr ; rr may be BC,DE,HL,AF
- pop rr | x1 | 12 | (AF) | rr=(SP) SP=SP+2 ; rr may be BC,DE,HL,AF
-
-## 8-bit Arithmetic/Logic instructions
-
-Mnemonic | Encoding | Clock cycles | Flags | Description
------------------|----------|--------------|-------|-------------
- add A,r | 8x | 4 | z0hc | A=A+r
- add A,n | C6 nn | 8 | z0hc | A=A+n
- add A,(HL) | 86 | 8 | z0hc | A=A+(HL)
- adc A,r | 8x | 4 | z0hc | A=A+r+cy
- adc A,n | CE nn | 8 | z0hc | A=A+n+cy
- adc A,(HL) | 8E | 8 | z0hc | A=A+(HL)+cy
- sub r | 9x | 4 | z1hc | A=A-r
- sub n | D6 nn | 8 | z1hc | A=A-n
- sub (HL) | 96 | 8 | z1hc | A=A-(HL)
- sbc A,r | 9x | 4 | z1hc | A=A-r-cy
- sbc A,n | DE nn | 8 | z1hc | A=A-n-cy
- sbc A,(HL) | 9E | 8 | z1hc | A=A-(HL)-cy
- and r | Ax | 4 | z010 | A=A & r
- and n | E6 nn | 8 | z010 | A=A & n
- and (HL) | A6 | 8 | z010 | A=A & (HL)
- xor r | Ax | 4 | z000 | A=A xor r
- xor n | EE nn | 8 | z000 | A=A xor n
- xor (HL) | AE | 8 | z000 | A=A xor (HL)
- or r | Bx | 4 | z000 | A=A \| r
- or n | F6 nn | 8 | z000 | A=A \| n
- or (HL) | B6 | 8 | z000 | A=A \| (HL)
- cp r | Bx | 4 | z1hc | compare A-r
- cp n | FE nn | 8 | z1hc | compare A-n
- cp (HL) | BE | 8 | z1hc | compare A-(HL)
- inc r | xx | 4 | z0h- | r=r+1
- inc (HL) | 34 | 12 | z0h- | (HL)=(HL)+1
- dec r | xx | 4 | z1h- | r=r-1
- dec (HL) | 35 | 12 | z1h- | (HL)=(HL)-1
- daa | 27 | 4 | z-0c | decimal adjust A
- cpl | 2F | 4 | -11- | A = A xor FF
-
-## 16-bit Arithmetic/Logic instructions
-
-Mnemonic | Encoding | Clock cycles | Flags | Description
------------------|----------|--------------|-------|-------------
- add HL,rr | x9 | 8 | -0hc | HL = HL+rr ; rr may be BC,DE,HL,SP
- inc rr | x3 | 8 | ---- | rr = rr+1 ; rr may be BC,DE,HL,SP
- dec rr | xB | 8 | ---- | rr = rr-1 ; rr may be BC,DE,HL,SP
- add SP,dd | E8 dd | 16 | 00hc | SP = SP +/- dd ; dd is 8-bit signed number
- ld HL,SP+dd | F8 dd | 12 | 00hc | HL = SP +/- dd ; dd is 8-bit signed number
-
-## Rotate and Shift instructions
-
-Mnemonic | Encoding | Clock cycles | Flags | Description
------------------|----------|--------------|-------|-------------
- rlca | 07 | 4 | 000c | rotate A left
- rla | 17 | 4 | 000c | rotate A left through carry
- rrca | 0F | 4 | 000c | rotate A right
- rra | 1F | 4 | 000c | rotate A right through carry
- rlc r | CB 0x | 8 | z00c | rotate left
- rlc (HL) | CB 06 | 16 | z00c | rotate left
- rl r | CB 1x | 8 | z00c | rotate left through carry
- rl (HL) | CB 16 | 16 | z00c | rotate left through carry
- rrc r | CB 0x | 8 | z00c | rotate right
- rrc (HL) | CB 0E | 16 | z00c | rotate right
- rr r | CB 1x | 8 | z00c | rotate right through carry
- rr (HL) | CB 1E | 16 | z00c | rotate right through carry
- sla r | CB 2x | 8 | z00c | shift left arithmetic (b0=0)
- sla (HL) | CB 26 | 16 | z00c | shift left arithmetic (b0=0)
- swap r | CB 3x | 8 | z000 | exchange low/hi-nibble
- swap (HL) | CB 36 | 16 | z000 | exchange low/hi-nibble
- sra r | CB 2x | 8 | z00c | shift right arithmetic (b7=b7)
- sra (HL) | CB 2E | 16 | z00c | shift right arithmetic (b7=b7)
- srl r | CB 3x | 8 | z00c | shift right logical (b7=0)
- srl (HL) | CB 3E | 16 | z00c | shift right logical (b7=0)
-
-## Single-bit Operation instructions
-
-Mnemonic | Encoding | Clock cycles | Flags | Description
------------------|----------|--------------|-------|-------------
- bit n,r | CB xx | 8 | z01- | test bit n
- bit n,(HL) | CB xx | 12 | z01- | test bit n
- set n,r | CB xx | 8 | ---- | set bit n
- set n,(HL) | CB xx | 16 | ---- | set bit n
- res n,r | CB xx | 8 | ---- | reset bit n
- res n,(HL) | CB xx | 16 | ---- | reset bit n
-
-## CPU Control instructions
-
-Mnemonic | Encoding | Clock cycles | Flags | Description
------------------|----------|--------------|-------|-------------
- ccf | 3F | 4 | -00c | cy=cy xor 1
- scf | 37 | 4 | -001 | cy=1
- nop | 00 | 4 | ---- | no operation
- halt | 76 | N*4 | ---- | halt until interrupt occurs (low power)
- stop | 10 00 | ? | ---- | low power standby mode (VERY low power)
- di | F3 | 4 | ---- | disable interrupts, IME=0
- ei | FB | 4 | ---- | enable interrupts, IME=1
-
-## Jump instructions
-
-Mnemonic | Encoding | Clock cycles | Flags | Description
------------------|----------|--------------|-------|-------------
- jp nn | C3 nn nn | 16 | ---- | jump to nn, PC=nn
- jp HL | E9 | 4 | ---- | jump to HL, PC=HL
- jp f,nn | xx nn nn | 16/12 | ---- | conditional jump if nz,z,nc,c
- jr PC+dd | 18 dd | 12 | ---- | relative jump to nn (PC=PC+8-bit signed)
- jr f,PC+dd | xx dd | 12/8 | ---- | conditional relative jump if nz,z,nc,c
- call nn | CD nn nn | 24 | ---- | call to nn, SP=SP-2, (SP)=PC, PC=nn
- call f,nn | xx nn nn | 24/12 | ---- | conditional call if nz,z,nc,c
- ret | C9 | 16 | ---- | return, PC=(SP), SP=SP+2
- ret f | xx | 20/8 | ---- | conditional return if nz,z,nc,c
- reti | D9 | 16 | ---- | return and enable interrupts (IME=1)
- rst n | xx | 16 | ---- | call to 00,08,10,18,20,28,30,38
+:::tip
+
+If you are looking for textual explanations of what each each instruction does, please read [gbz80(7)](http://rgbds.gbdev.io/docs/gbz80.7); if you want a compact reference card/cheat sheet of each opcode and its flag effects, please consult [the optables](http://gbdev.io/gb-opcodes/optables) (whose [octal view](http://gbdev.io/gb-opcodes/optables/octal) makes most encoding patterns more apparent).
+
+:::
+
+
+
+The Game Boy's SM83 processor possesses a CISC, variable-length instruction set.
+This page attempts to shed some light on how the CPU decodes the raw bytes fed into it into instructions.
+
+The first byte of each instruction is typically called the "opcode" (for "operation code").
+By noticing that some instructions perform identical operations but with different parameters, they can be grouped together; for example, `inc bc`, `inc de`, `inc hl`, and `inc sp` differ only in what 16-bit register they modify.
+
+In each table, one line represents one such grouping.
+Since many groupings have some variation, the variation has to be encoded in the instruction; for example, the above four instructions will be collectively referred to as `inc r16`.
+Here are the possible placeholders and their values:
+
+{{#bits 8 <
+ "r8" 0:"b
" 1:"c
" 2:"d
" 3:"e
" 4:"h
" 5:"l
" 6:"[hl]
" 7:"a
" ;
+ "r16" 0:"bc
" 1:"de
" 2:"hl
" 3:"sp
" ;
+ "r16stk" 0:"bc
" 1:"de
" 2:"hl
" 3:"af
" ;
+ "r16mem" 0:"bc
" 1:"de
" 2:"hl+
" 3:"hl-
" ;
+ "cond" 0:"nz
" 1:"z
" 2:"nc
" 3:"c
" ;
+ "b3" 0-7:"A 3-bit bit index" ;
+ "tgt3" 0-7:"rst
's target address, divided by 8" ;
+ "imm8" 0-7:"The following byte" ;
+ "imm16" 0-7:"The following two bytes, in little-endian order" ;
+}}
+
+These last two are a little special: if they are present in the instruction's mnemonic, it means that the instruction is 1 (`imm8`) / 2 (`imm16`) extra bytes long.
+
+:::tip
+
+`[hl+]` and `[hl-]` can also be notated `[hli]` and `[hld]` respectively (as in **i**ncrement and **d**ecrement).
+
+:::
+
+Groupings have been loosely associated based on what they do into separate tables; those have no particular ordering, and are purely for readability and convenience.
+Finally, the instruction "families" have been further grouped into four "blocks", differentiated by the first two bits of the opcode.
+
+## Block 0
+
+{{#bits 8 >
+ "nop
" 7:"0" 6:"0" 5:"0" 4:"0" 3:"0" 2:"0" 1:"0" 0:"0"
+}}
+
+{{#bits 8 >
+ "ld r16, imm16
" 7:"0" 6:"0" 5-4:"Dest (r16)" 3:"0" 2:"0" 1:"0" 0:"1" ;
+ "ld [r16mem], a
" 7:"0" 6:"0" 5-4:"Dest (r16mem)" 3:"0" 2:"0" 1:"1" 0:"0" ;
+ "ld a, [r16mem]
" 7:"0" 6:"0" 5-4:"Source (r16mem)" 3:"1" 2:"0" 1:"1" 0:"0" ;
+ "ld [imm16], sp
" 7:"0" 6:"0" 5:"0" 4:"0" 3:"1" 2:"0" 1:"0" 0:"0" ;
+}}
+
+{{#bits 8 >
+ "inc r16
" 7:"0" 6:"0" 5-4:"Operand (r16)" 3:"0" 2:"0" 1:"1" 0:"1" ;
+ "dec r16
" 7:"0" 6:"0" 5-4:"Operand (r16)" 3:"1" 2:"0" 1:"1" 0:"1" ;
+ "add hl, r16
" 7:"0" 6:"0" 5-4:"Operand (r16)" 3:"1" 2:"0" 1:"0" 0:"1" ;
+}}
+
+{{#bits 8 >
+ "inc r8
" 7:"0" 6:"0" 5-3:"Operand (r8)" 2:"1" 1:"0" 0:"0" ;
+ "dec r8
" 7:"0" 6:"0" 5-3:"Operand (r8)" 2:"1" 1:"0" 0:"1" ;
+}}
+
+{{#bits 8 >
+ "ld r8, imm8
" 7:"0" 6:"0" 5-3:"Dest (r8)" 2:"1" 1:"1" 0:"0"
+}}
+
+{{#bits 8 >
+ "rlca
" 7:"0" 6:"0" 5:"0" 4:"0" 3:"0" 2:"1" 1:"1" 0:"1" ;
+ "rrca
" 7:"0" 6:"0" 5:"0" 4:"0" 3:"1" 2:"1" 1:"1" 0:"1" ;
+ "rla
" 7:"0" 6:"0" 5:"0" 4:"1" 3:"0" 2:"1" 1:"1" 0:"1" ;
+ "rra
" 7:"0" 6:"0" 5:"0" 4:"1" 3:"1" 2:"1" 1:"1" 0:"1" ;
+ "daa
" 7:"0" 6:"0" 5:"1" 4:"0" 3:"0" 2:"1" 1:"1" 0:"1" ;
+ "cpl
" 7:"0" 6:"0" 5:"1" 4:"0" 3:"1" 2:"1" 1:"1" 0:"1" ;
+ "scf
" 7:"0" 6:"0" 5:"1" 4:"1" 3:"0" 2:"1" 1:"1" 0:"1" ;
+ "ccf
" 7:"0" 6:"0" 5:"1" 4:"1" 3:"1" 2:"1" 1:"1" 0:"1" ;
+}}
+
+{{#bits 8 >
+ "jr imm8
" 7:"0" 6:"0" 5:"0" 4:"1" 3:"1" 2:"0" 1:"0" 0:"0" ;
+ "jr cond, imm8
" 7:"0" 6:"0" 5:"1" 4-3:"Condition (cond)" 2:"0" 1:"0" 0:"0" ;
+}}
+
+{{#bits 8 >
+ "stop
" 7:"0" 6:"0" 5:"0" 4:"1" 3:"0" 2:"0" 1:"0" 0:"0"
+}}
+
+[`stop`](<#Using the STOP Instruction>) is often considered a **two-byte** instruction, though [the second byte is not always ignored](https://gist.github.com/SonoSooS/c0055300670d678b5ae8433e20bea595#nop-and-stop).
+
+## Block 1: 8-bit register-to-register loads
+
+{{#bits 8 >
+ "ld r8, r8
" 7:"0" 6:"1" 5-3:"Dest (r8)" 2-0:"Source (r8)"
+}}
+
+**Exception**: trying to encode `ld [hl], [hl]` instead yields [the `halt` instruction](<#halt>):
+
+{{#bits 8 >
+ "halt
" 7:"0" 6:"1" 5:"1" 4:"1" 3:"0" 2:"1" 1:"1" 0:"0"
+}}
+
+## Block 2: 8-bit arithmetic
+
+{{#bits 8 >
+ "add a, r8
" 7:"1" 6:"0" 5:"0" 4:"0" 3:"0" 2-0:"Operand (r8)" ;
+ "adc a, r8
" 7:"1" 6:"0" 5:"0" 4:"0" 3:"1" 2-0:"Operand (r8)" ;
+ "sub a, r8
" 7:"1" 6:"0" 5:"0" 4:"1" 3:"0" 2-0:"Operand (r8)" ;
+ "sbc a, r8
" 7:"1" 6:"0" 5:"0" 4:"1" 3:"1" 2-0:"Operand (r8)" ;
+ "and a, r8
" 7:"1" 6:"0" 5:"1" 4:"0" 3:"0" 2-0:"Operand (r8)" ;
+ "xor a, r8
" 7:"1" 6:"0" 5:"1" 4:"0" 3:"1" 2-0:"Operand (r8)" ;
+ "or a, r8
" 7:"1" 6:"0" 5:"1" 4:"1" 3:"0" 2-0:"Operand (r8)" ;
+ "cp a, r8
" 7:"1" 6:"0" 5:"1" 4:"1" 3:"1" 2-0:"Operand (r8)" ;
+}}
+
+## Block 3
+
+{{#bits 8 >
+ "add a, imm8
" 7:"1" 6:"1" 5:"0" 4:"0" 3:"0" 2:"1" 1:"1" 0:"0" ;
+ "adc a, imm8
" 7:"1" 6:"1" 5:"0" 4:"0" 3:"1" 2:"1" 1:"1" 0:"0" ;
+ "sub a, imm8
" 7:"1" 6:"1" 5:"0" 4:"1" 3:"0" 2:"1" 1:"1" 0:"0" ;
+ "sbc a, imm8
" 7:"1" 6:"1" 5:"0" 4:"1" 3:"1" 2:"1" 1:"1" 0:"0" ;
+ "and a, imm8
" 7:"1" 6:"1" 5:"1" 4:"0" 3:"0" 2:"1" 1:"1" 0:"0" ;
+ "xor a, imm8
" 7:"1" 6:"1" 5:"1" 4:"0" 3:"1" 2:"1" 1:"1" 0:"0" ;
+ "or a, imm8
" 7:"1" 6:"1" 5:"1" 4:"1" 3:"0" 2:"1" 1:"1" 0:"0" ;
+ "cp a, imm8
" 7:"1" 6:"1" 5:"1" 4:"1" 3:"1" 2:"1" 1:"1" 0:"0" ;
+}}
+
+{{#bits 8 >
+ "ret cond
" 7:"1" 6:"1" 5:"0" 4-3:"Condition (cond)" 2:"0" 1:"0" 0:"0" ;
+ "ret
" 7:"1" 6:"1" 5:"0" 4:"0" 3:"1" 2:"0" 1:"0" 0:"1" ;
+ "reti
" 7:"1" 6:"1" 5:"0" 4:"1" 3:"1" 2:"0" 1:"0" 0:"1" ;
+ "jp cond, imm16
" 7:"1" 6:"1" 5:"0" 4-3:"Condition (cond)" 2:"0" 1:"1" 0:"0" ;
+ "jp imm16
" 7:"1" 6:"1" 5:"0" 4:"0" 3:"0" 2:"0" 1:"1" 0:"1" ;
+ "jp hl
" 7:"1" 6:"1" 5:"1" 4:"0" 3:"1" 2:"0" 1:"0" 0:"1" ;
+ "call cond, imm16
" 7:"1" 6:"1" 5:"0" 4-3:"Condition (cond)" 2:"1" 1:"0" 0:"0" ;
+ "call imm16
" 7:"1" 6:"1" 5:"0" 4:"0" 3:"1" 2:"1" 1:"0" 0:"1" ;
+ "rst tgt3
" 7:"1" 6:"1" 5-3:"Target (tgt3)" 2:"1" 1:"1" 0:"1" ;
+}}
+
+{{#bits 8 >
+ "pop r16stk
" 7:"1" 6:"1" 5-4:"Register (r16stk)" 3:"0" 2:"0" 1:"0" 0:"1" ;
+ "push r16stk
" 7:"1" 6:"1" 5-4:"Register (r16stk)" 3:"0" 2:"1" 1:"0" 0:"1" ;
+}}
+
+{{#bits 8 >
+ "Prefix (see block below)" 7:"1" 6:"1" 5:"0" 4:"0" 3:"1" 2:"0" 1:"1" 0:"1"
+}}
+
+{{#bits 8 >
+ "ldh [c], a
" 7:"1" 6:"1" 5:"1" 4:"0" 3:"0" 2:"1" 1:"0" 0:"0" ;
+ "ldh [imm8], a
" 7:"1" 6:"1" 5:"1" 4:"0" 3:"0" 2:"0" 1:"0" 0:"0" ;
+ "ld [imm16], a
" 7:"1" 6:"1" 5:"1" 4:"0" 3:"1" 2:"1" 1:"0" 0:"0" ;
+ "ldh a, [c]
" 7:"1" 6:"1" 5:"1" 4:"1" 3:"0" 2:"1" 1:"0" 0:"0" ;
+ "ldh a, [imm8]
" 7:"1" 6:"1" 5:"1" 4:"1" 3:"0" 2:"0" 1:"0" 0:"0" ;
+ "ld a, [imm16]
" 7:"1" 6:"1" 5:"1" 4:"1" 3:"1" 2:"1" 1:"0" 0:"0" ;
+}}
+
+{{#bits 8 >
+ "add sp, imm8
" 7:"1" 6:"1" 5:"1" 4:"0" 3:"1" 2:"0" 1:"0" 0:"0" ;
+ "ld hl, sp + imm8
" 7:"1" 6:"1" 5:"1" 4:"1" 3:"1" 2:"0" 1:"0" 0:"0" ;
+ "ld sp, hl
" 7:"1" 6:"1" 5:"1" 4:"1" 3:"1" 2:"0" 1:"0" 0:"1" ;
+}}
+
+{{#bits 8 >
+ "di
" 7:"1" 6:"1" 5:"1" 4:"1" 3:"0" 2:"0" 1:"1" 0:"1" ;
+ "ei
" 7:"1" 6:"1" 5:"1" 4:"1" 3:"1" 2:"0" 1:"1" 0:"1" ;
+}}
+
+The following opcodes are **invalid**, and [hard-lock the CPU](https://gist.github.com/SonoSooS/c0055300670d678b5ae8433e20bea595#opcode-holes-not-implemented-opcodes) until the console is powered off: \$D3, \$DB, \$DD, \$E3, \$E4, \$EB, \$EC, \$ED, \$F4, \$FC, and \$FD.
+
+## \$CB prefix instructions
+
+{{#bits 8 >
+ "rlc r8
" 7:"0" 6:"0" 5:"0" 4:"0" 3:"0" 2-0:"Operand (r8)" ;
+ "rrc r8
" 7:"0" 6:"0" 5:"0" 4:"0" 3:"1" 2-0:"Operand (r8)" ;
+ "rl r8
" 7:"0" 6:"0" 5:"0" 4:"1" 3:"0" 2-0:"Operand (r8)" ;
+ "rr r8
" 7:"0" 6:"0" 5:"0" 4:"1" 3:"1" 2-0:"Operand (r8)" ;
+ "sla r8
" 7:"0" 6:"0" 5:"1" 4:"0" 3:"0" 2-0:"Operand (r8)" ;
+ "sra r8
" 7:"0" 6:"0" 5:"1" 4:"0" 3:"1" 2-0:"Operand (r8)" ;
+ "swap r8
" 7:"0" 6:"0" 5:"1" 4:"1" 3:"0" 2-0:"Operand (r8)" ;
+ "srl r8
" 7:"0" 6:"0" 5:"1" 4:"1" 3:"1" 2-0:"Operand (r8)" ;
+}}
+
+{{#bits 8 >
+ "bit b3, r8
" 7:"0" 6:"1" 5-3:"Bit index (b3)" 2-0:"Operand (r8)" ;
+ "res b3, r8
" 7:"1" 6:"0" 5-3:"Bit index (b3)" 2-0:"Operand (r8)" ;
+ "set b3, r8
" 7:"1" 6:"1" 5-3:"Bit index (b3)" 2-0:"Operand (r8)" ;
+}}