The GBZ80 (Sharp SM83) is the CPU that powers the original Nintendo Gameboy and Gameboy Color handheld consoles. It is kind of an in-between the Intel 8080 and Z80.
The GBZ80 lacks the alternate register set, the dedicated I/O bus, the R register (thus no M1), the index registers (thus no DD and FD prefixed opcodes), the ED prefixed opcodes (including block transfer), the sign and parity/overflow flags (and all conditional instructions that used them), the undocumented flags (thus no leaking of WZ and Q internal registers). GBZ80 opcodes
The GBZ80 also lacks the NMI pin (thus no IFF2 and no RETN), the IM instructions and the I register. It has a different interrupt system than the Z80. Source
The Nintendo documentation does not mention M-cycles or T-states at all. They only mention CPU cycles, which are always equal to 4 T-states (like NOPs in the CPC world). Also, the GBZ80 has different timings than the Z80. For example:
- CALL nn takes 6 cycles on the GBZ80, but 5 NOPs on the Z80
- ADD HL,ss takes 2 cycles on the GBZ80, but 3 NOPs on the Z80
- JP cc,nn has different timings depending on whether the jump is taken. This is not the case on Z80.
Flags can differ too:
- RLCA, RRCA, RLA, RRA clear ZF in the GBZ80, but not in the Z80
- DAA clears HF in the GBZ80, but not in the Z80
Fun fact: Way more GBZ80 cores were produced for Gameboy hardware (118 million Gameboys and 81 million GBA) than all the Z80 chips produced for home computers and game consoles.
Register File
Register | Size | Description | Notes |
---|---|---|---|
B, C, D, E, H, L | 8-bit | General-purpose registers | Can form 16-bit pairs: BC, DE, HL |
A (Accumulator) | 8-bit | Main register for arithmetic, logic, and data transfer | Most used register |
F (Flags) | 8-bit |
|
NF and HF are used in the DAA algorithm |
SP (Stack Pointer) | 16-bit | Points to top of the stack | Used for subroutine calls and interrupt handling |
PC (Program Counter) | 16-bit | Points to the next instruction | Automatically increments as instructions execute |
GBZ80 instructions
Legend:
- r,s: 000=B, 001=C, 010=D, 011=E, 100=H, 101=L, 111=A (110 is treated separately)
- pp: 00=BC, 01=DE, 10=HL, 11=SP
- qq: 00=BC, 01=DE, 10=HL, 11=AF
- cc: 00=NZ, 01=Z, 10=NC, 11=C
Load group
Instruction | Opcode | Cycles | Z | N | H | C | Effect | Description |
---|---|---|---|---|---|---|---|---|
ld r,s | 01rrrsss | 1 | - | - | - | - | r := s | 8-bit Load |
ld (hl),r | 01110rrr | 2 | (hl) := r | |||||
ld r,(hl) | 01rrr110 | 2 | r := (hl) | |||||
ld r,n | 00rrr110 nnnnnnnn | 2 | r := n | |||||
ld (hl),n | 00110110 nnnnnnnn | 3 | (hl) := n | |||||
ld (bc),a | 00000010 | 2 | (bc) := a | |||||
ld a,(bc) | 00001010 | 2 | a := (bc) | |||||
ld (de),a | 00010010 | 2 | (de) := a | |||||
ld a,(de) | 00011010 | 2 | a := (de) | |||||
ld (hli),a | 00100010 | 2 | (hl) := a, hl += 1 | |||||
ld a,(hli) | 00101010 | 2 | a := (hl), hl += 1 | |||||
ld (hld),a | 00110010 | 2 | (hl) := a, hl -= 1 | |||||
ld a,(hld) | 00111010 | 2 | a := (hl), hl -= 1 | |||||
ld (nn),a | 11101010 lolololo hihihihi | 4 | (nn) := a | |||||
ld a,(nn) | 11111010 lolololo hihihihi | 4 | a := (nn) | |||||
ld (n),a | 11100000 nnnnnnnn | 3 | - | - | - | - | (FF00h + n) := a | 8-bit I/O Load |
ld a,(n) | 11110000 nnnnnnnn | 3 | a := (FF00h + n) | |||||
ld (c),a | 11100010 | 2 | (FF00h + c) := a | |||||
ld a,(c) | 11110010 | 2 | a := (FF00h + c) | |||||
ld pp,nn | 00pp0001 lolololo hihihihi | 3 | - | - | - | - | pp := nn | 16-bit Load |
ld (nn),sp | 00001000 lolololo hihihihi | 5 | (nn) := sp | |||||
ld sp,hl | 11111001 | 2 | sp := hl | |||||
pop qq | 11qq0001 | 3 | - | - | - | - | qq := (sp), sp += 2 | Pop a value from the stack |
push qq | 11qq0101 | 4 | - | - | - | - | sp -= 2, (sp) := qq | Push a value onto the stack |
16-bit Arithmetic group
Instruction | Opcode | Cycles | Z | N | H | C | Effect | Description |
---|---|---|---|---|---|---|---|---|
inc pp | 00pp0011 | 2 | - | - | - | - | pp += 1 | Increment |
dec pp | 00pp1011 | 2 | - | - | - | - | pp -= 1 | Decrement |
add hl,pp | 00pp1001 | 2 | - | 0 | + | + | hl += pp | Add |
add sp,e | 11101000 eeeeeeee | 4 | 0 | 0 | + | + | sp += e | |
ldhl sp,e | 11111000 eeeeeeee | 3 | 0 | 0 | + | + | hl := sp + e |
8-bit ALU group
Instruction | Opcode | Cycles | Z | N | H | C | Effect | Description |
---|---|---|---|---|---|---|---|---|
inc r | 00rrr100 | 1 | + | 0 | + | - | r += 1 | Increment |
inc (hl) | 00110100 | 3 | (hl) += 1 | |||||
dec r | 00rrr101 | 1 | + | 1 | + | - | r -= 1 | Decrement |
dec (hl) | 00110101 | 3 | (hl) -= 1 | |||||
add a,r | 10000rrr | 1 | + | 0 | + | + | a += r | Add |
add a,(hl) | 10000110 | 2 | a += (hl) | |||||
add a,n | 11000110 nnnnnnnn | 2 | a += n | |||||
adc a,r | 10001rrr | 1 | + | 0 | + | + | a += r + cf | Add with Carry |
adc a,(hl) | 10001110 | 2 | a += (hl) + cf | |||||
adc a,n | 11001110 nnnnnnnn | 2 | a += n + cf | |||||
sub r | 10010rrr | 1 | + | 1 | + | + | a -= r | Subtract |
sub (hl) | 10010110 | 2 | a -= (hl) | |||||
sub n | 11010110 nnnnnnnn | 2 | a -= n | |||||
sbc a,r | 10011rrr | 1 | + | 1 | + | + | a -= r + cf | Subtract with Carry |
sbc a,(hl) | 10011110 | 2 | a -= (hl) + cf | |||||
sbc a,n | 11011110 nnnnnnnn | 2 | a -= n + cf | |||||
cp r | 10111rrr | 1 | + | 1 | + | + | tmp := a - r | Compare |
cp (hl) | 10111110 | 2 | tmp := a - (hl) | |||||
cp n | 11111110 nnnnnnnn | 2 | tmp := a - n | |||||
and r | 10100rrr | 1 | + | 0 | 1 | 0 | a := a and r | Logical AND |
and (hl) | 10100110 | 2 | a := a and (hl) | |||||
and n | 11100110 nnnnnnnn | 2 | a := a and n | |||||
xor r | 10101rrr | 1 | + | 0 | 0 | 0 | a := a xor r | Logical eXclusive OR |
xor (hl) | 10101110 | 2 | a := a xor (hl) | |||||
xor n | 11101110 nnnnnnnn | 2 | a := a xor n | |||||
or r | 10110rrr | 1 | + | 0 | 0 | 0 | a := a or r | Logical Inclusive OR |
or (hl) | 10110110 | 2 | a := a or (hl) | |||||
or n | 11110110 nnnnnnnn | 2 | a := a or n | |||||
daa | 00100111 | 1 | + | - | 0 | X | tmp := a,
if nf: if hf or [a and 0x0f > 9]: tmp -= 0x06 if cf or [a > 0x99]: tmp -= 0x60 else: if hf or [a and 0x0f > 9]: tmp += 0x06 if cf or [a > 0x99]: tmp += 0x60 tmp => flags, cf := cf or [a > 0x99], a := tmp |
Decimal Adjust Accumulator |
ROT group
Instruction | Opcode | Cycles | Z | N | H | C | Effect | Description |
---|---|---|---|---|---|---|---|---|
rlca | 00000111 | 1 | 0 | 0 | 0 | X | cf := a.7, a := [a << 1] + cf | Fast Rotate |
rrca | 00001111 | 1 | cf := a.0, a := [a >> 1] + [cf << 7] | |||||
rla | 00010111 | 1 | ocf := cf, cf := a.7, a := [a << 1] + ocf | |||||
rra | 00011111 | 1 | ocf := cf, cf := a.0, a := [a >> 1] + [ocf << 7] | |||||
rl r | CB 00010rrr | 2 | + | 0 | 0 | X | ocf := cf, cf := r.7, r := [r << 1] + ocf | Rotate Left |
rl (hl) | CB 00010110 | 4 | ocf := cf, cf := (hl).7, (hl) := [(hl) << 1] + ocf | |||||
rlc r | CB 00000rrr | 2 | + | 0 | 0 | X | cf := r.7, r := [r << 1] + cf | Rotate Left Carry |
rlc (hl) | CB 00000110 | 4 | cf := (hl).7, (hl) := [(hl) << 1] + cf | |||||
rr r | CB 00011rrr | 2 | + | 0 | 0 | X | ocf := cf, cf := r.0, r := [r >> 1] + [ocf << 7] | Rotate Right |
rr (hl) | CB 00011110 | 4 | ocf := cf, cf := (hl).0, (hl) := [(hl) >> 1] + [ocf << 7] | |||||
rrc r | CB 00001rrr | 2 | + | 0 | 0 | X | cf := r.0, r := [r >> 1] + [cf << 7] | Rotate Right Carry |
rrc (hl) | CB 00001110 | 4 | cf := (hl).0, (hl) := [(hl) >> 1] + [cf << 7] | |||||
sla r | CB 00100rrr | 2 | + | 0 | 0 | X | cf := r.7, r := r << 1 | Shift Left Arithmetic |
sla (hl) | CB 00100110 | 4 | cf := (hl).7, (hl) := (hl) << 1 | |||||
sra r | CB 00101rrr | 2 | + | 0 | 0 | X | cf := r.0, r := r >> 1, r.7 := r.6 | Shift Right Arithmetic |
sra (hl) | CB 00101110 | 4 | cf := (hl).0, (hl) := (hl) >> 1, (hl).7 := (hl).6 | |||||
srl r | CB 00111rrr | 2 | + | 0 | 0 | X | cf := r.0, r := r >> 1 | Shift Right Logical |
srl (hl) | CB 00111110 | 4 | cf := (hl).0, (hl) := (hl) >> 1 | |||||
swap r | CB 00110rrr | 2 | + | 0 | 0 | 0 | r := [[r and 0x0f] << 4] + [r >> 4] | Swap nibbles |
swap (hl) | CB 00110110 | 4 | (hl) := [[(hl) and 0x0f] << 4] + [(hl) >> 4] |
Bitwise group
Instruction | Opcode | Cycles | Z | N | H | C | Effect | Description |
---|---|---|---|---|---|---|---|---|
bit b,r | CB 01bbbrrr | 2 | + | 0 | 1 | - | tmp := r and [1 << b] | Test Bit |
bit b,(hl) | CB 01bbb110 | 3 | tmp := (hl) and [1 << b] | |||||
res b,r | CB 10bbbrrr | 2 | - | - | - | - | r := r and ~[1 << b] | Reset Bit |
res b,(hl) | CB 10bbb110 | 4 | (hl) := (hl) and ~[1 << b] | |||||
set b,r | CB 11bbbrrr | 2 | - | - | - | - | r := r or [1 << b] | Set Bit |
set b,(hl) | CB 11bbb110 | 4 | (hl) := (hl) or [1 << b] | |||||
cpl | 00101111 | 1 | - | 1 | 1 | - | a := ~a | Complement |
Control flow group
Instruction | Opcode | Cycles | Z | N | H | C | Effect | Description |
---|---|---|---|---|---|---|---|---|
rst t | 11ttt111 | 4 | - | - | - | - | sp -= 2, (sp) := pc, pc := t | Restart
ttt: 000=#0, 001=#8, 010=#10, 011=#18, 100=#20, 101=#28, 110=#30, 111=#38 |
call nn | 11001101 lolololo hihihihi | 6 | sp -= 2, (sp) := pc, pc := nn | Call | ||||
call cc,nn | 110cc100 lolololo hihihihi | 6/3 | if cc then sp -= 2, (sp) := pc, pc := nn | |||||
jp nn | 11000011 lolololo hihihihi | 4 | - | - | - | - | pc := nn | Jump |
jp (hl) | 11101001 | 1 | pc := hl | |||||
jp cc,nn | 110cc010 lolololo hihihihi | 4/3 | if cc then pc := nn | |||||
jr e | 00011000 eeeeeeee | 3 | - | - | - | - | pc += e | Relative jump |
jr cc,e | 001cc000 eeeeeeee | 3/2 | if cc then pc += e | |||||
ret | 11001001 | 4 | - | - | - | - | pc := (sp), sp += 2 | Return |
ret cc | 110cc000 | 5/2 | if cc then pc := (sp), sp += 2 | |||||
reti | 11011001 | 4 | pc := (sp), sp += 2, ime := 1 | Return from Interrupt |
CPU control group
Instruction | Opcode | Cycles | Z | N | H | C | Effect | Description |
---|---|---|---|---|---|---|---|---|
di | 11110011 | 1 | - | - | - | - | ime := 0 | Disable Interrupts |
ei | 11111011 | 1 | - | - | - | - | ime := 1 | Enable Interrupts |
halt | 01110110 | 1 | - | - | - | - | wait for interrupt | Suspends CPU operation |
stop | 00010000 00000000 | 1 | - | - | - | - | wait for reset signal | Stops the system clock and LCD controller |
nop | 00000000 | 1 | - | - | - | - | nothing | No Operation |
scf | 00110111 | 1 | - | 0 | 0 | 1 | nothing else | Set Carry Flag |
ccf | 00111111 | 1 | - | 0 | X | X | hf := cf, cf := ~cf | Complement Carry Flag |
Opcodes
Opcode differences with Z80 are in bold. The unused (—) opcodes will lock up the Game Boy CPU when used. The assembler syntax is from the official Nintendo Gameboy programming manual.
Standard opcodes
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CB-prefixed opcodes
|
|
|
|
|
|
|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
Oddities
- On GBZ80, when an interrupt is triggered, the CPU automatically performs a DI before jumping to the interrupt handler. The Z80 does not.
- On GBZ80, RETI automatically performs an EI. The Z80 does not. Source
- STOP is normally a 2-byte instruction where the second byte is ignored. Source
- STOP is used on Gameboy Color to switch between normal speed and double speed CPU modes.
- RST instructions are just a CALL instruction to a fixed address baked in the instruction itself.
- Despite what the syntax of the instructions JP (HL/IX/IY) suggests, PC will be loaded with the contents of the register itself, not the indexed value. Those instructions should be understood as JP HL/IX/IY.
- The instructions LD A,A, LD B,B, LD C,C, LD D,D, LD E,E, LD H,H and LD L,L are useless. Their existence is just a side effect of how instructions are encoded as opcodes in the CPU. However, some Game Boy emulators (such as BGB) interpret LD B,B as a breakpoint, or LD D,D as a debug message.
- While the syntax of the 8-bit ADD, ADC and SBC instructions all explicitly mention the A register, the SUB instruction does not mention it.
- Arithmetic can only really be done on the A register.
- PUSH and POP instructions utilize a 16-bit operand and the high-order byte is always pushed first and popped last. PUSH HL is PUSH H then L. POP HL is POP L then H.
- ADD SP,e takes 4 cycles, while LDHL SP,e takes only 3 cycles.