GBZ80(7)

๐Ÿ“ฆ
version 1.0.4 ยท 4 versions
, in arch rolling, nixpkgs unstable

๐Ÿ’– NAME ๐Ÿ’–

gbz80 โ€” Game Boy CPU instruction reference. okay so bestie, this is gbz80(7), the glow-up reference for the Game Boy CPU instructions, and we're getting into it ๐Ÿ’….


โœจ DESCRIPTION โœจ

okay so here's the tea: this is the list of instructions supported by rgbasm(1), including a short description, the number of bytes needed to encode them, and the number of CPU cycles at 1MHz (or 2MHz in GBC double speed mode) needed to complete them. no cap, every byte and cycle matters ๐Ÿ’–.

Instructions are documented according to the syntax accepted by rgbasm(1), which does not always match one-to-one with the way instructions are encoded: https://gbdev.io/gb-opcodes/optables/.

Note: All arithmetic and logic instructions that use register A as a destination can omit the destination, since it is assumed to be register A by default. So the following two lines have the same effect:

OR A,B
OR B

Furthermore, the CPL instruction can take an optional A destination, since it can only be register A. So the following two lines have the same effect:

CPL
CPL A

๐Ÿงš LEGEND ๐Ÿงš

List of abbreviations used in this document. lowkey essential, bestie ๐Ÿซถ.

  • r8 โ€” Any of the 8-bit registers (A, B, C, D, E, H, L).
  • r16 โ€” Any of the general-purpose 16-bit registers (BC, DE, HL).
  • n8 โ€” 8-bit integer constant (signed or unsigned, -128 to 255).
  • n16 โ€” 16-bit integer constant (signed or unsigned, -32768 to 65535).
  • e8 โ€” 8-bit signed offset (-128 to 127).
  • u3 โ€” 3-bit unsigned bit index (0 to 7, with 0 as the least significant bit).
  • cc โ€” A condition code:
    • Z โ€” Execute if Z is set.
    • NZ โ€” Execute if Z is not set.
    • C โ€” Execute if C is set.
    • NC โ€” Execute if C is not set.
  • vec โ€” An RST vector (0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, and 0x38).

๐ŸŒˆ INSTRUCTION OVERVIEW ๐ŸŒˆ

๐ŸŽ€ Load instructions ๐ŸŽ€

  • LD r8,r8
  • LD r8,n8
  • LD r16,n16
  • LD [HL],r8
  • LD [HL],n8
  • LD r8,[HL]
  • LD [r16],A
  • LD [n16],A
  • LDH [n16],A
  • LDH [C],A
  • LD A,[r16]
  • LD A,[n16]
  • LDH A,[n16]
  • LDH A,[C]
  • LD [HLI],A
  • LD [HLD],A
  • LD A,[HLI]
  • LD A,[HLD]

๐Ÿงฎ 8-bit arithmetic instructions ๐Ÿงฎ

  • ADC A,r8
  • ADC A,[HL]
  • ADC A,n8
  • ADD A,r8
  • ADD A,[HL]
  • ADD A,n8
  • CP A,r8
  • CP A,[HL]
  • CP A,n8
  • DEC r8
  • DEC [HL]
  • INC r8
  • INC [HL]
  • SBC A,r8
  • SBC A,[HL]
  • SBC A,n8
  • SUB A,r8
  • SUB A,[HL]
  • SUB A,n8

๐Ÿงฎ 16-bit arithmetic instructions ๐Ÿงฎ

  • ADD HL,r16
  • DEC r16
  • INC r16

๐Ÿฆ‹ Bitwise logic instructions ๐Ÿฆ‹

  • AND A,r8
  • AND A,[HL]
  • AND A,n8
  • CPL
  • OR A,r8
  • OR A,[HL]
  • OR A,n8
  • XOR A,r8
  • XOR A,[HL]
  • XOR A,n8

๐ŸŽ€ Bit flag instructions ๐ŸŽ€

  • BIT u3,r8
  • BIT u3,[HL]
  • RES u3,r8
  • RES u3,[HL]
  • SET u3,r8
  • SET u3,[HL]

๐ŸŒ€ Bit shift instructions ๐ŸŒ€

  • RL r8
  • RL [HL]
  • RLA
  • RLC r8
  • RLC [HL]
  • RLCA
  • RR r8
  • RR [HL]
  • RRA
  • RRC r8
  • RRC [HL]
  • RRCA
  • SLA r8
  • SLA [HL]
  • SRA r8
  • SRA [HL]
  • SRL r8
  • SRL [HL]
  • SWAP r8
  • SWAP [HL]

๐Ÿ’ซ Jumps and subroutine instructions ๐Ÿ’ซ

  • CALL n16
  • CALL cc,n16
  • JP HL
  • JP n16
  • JP cc,n16
  • JR n16
  • JR cc,n16
  • RET cc
  • RET
  • RETI
  • RST vec

๐Ÿšฉ Carry flag instructions ๐Ÿšฉ

  • CCF
  • SCF

๐Ÿฅž Stack manipulation instructions ๐Ÿฅž

  • ADD HL,SP
  • ADD SP,e8
  • DEC SP
  • INC SP
  • LD SP,n16
  • LD [n16],SP
  • LD HL,SP+e8
  • LD SP,HL
  • POP AF
  • POP r16
  • PUSH AF
  • PUSH r16
  • DI
  • EI
  • HALT

๐Ÿ“ Miscellaneous instructions ๐Ÿ“

  • DAA
  • NOP
  • STOP

๐Ÿ‘‘ INSTRUCTION REFERENCE ๐Ÿ‘‘

๐Ÿ’… ADC A,r8 ๐Ÿ’…

Add the value in r8 plus the carry flag to A. bestie, that carry flag is coming along for the ride โœจ.

Cycles: 1

Bytes: 1

Flags:

  • Z โ€” Set if result is 0.
  • N โ€” 0.
  • H โ€” Set if overflow from bit 3.
  • C โ€” Set if overflow from bit 7.

๐Ÿ’… ADC A,[HL] ๐Ÿ’…

Add the byte pointed to by HL plus the carry flag to A.

Cycles: 2

Bytes: 1

Flags: See ADC A,r8.

๐Ÿ’… ADC A,n8 ๐Ÿ’…

Add the value n8 plus the carry flag to A.

Cycles: 2

Bytes: 2

Flags: See ADC A,r8.

๐Ÿ’… ADD A,r8 ๐Ÿ’…

Add the value in r8 to A.

Cycles: 1

Bytes: 1

Flags:

  • Z โ€” Set if result is 0.
  • N โ€” 0.
  • H โ€” Set if overflow from bit 3.
  • C โ€” Set if overflow from bit 7.

๐Ÿ’… ADD A,[HL] ๐Ÿ’…

Add the byte pointed to by HL to A.

Cycles: 2

Bytes: 1

Flags: See ADD A,r8.

๐Ÿ’… ADD A,n8 ๐Ÿ’…

Add the value n8 to A.

Cycles: 2

Bytes: 2

Flags: See ADD A,r8.

๐Ÿ’… ADD HL,r16 ๐Ÿ’…

Add the value in r16 to HL.

Cycles: 2

Bytes: 1

Flags:

  • N โ€” 0.
  • H โ€” Set if overflow from bit 11.
  • C โ€” Set if overflow from bit 15.

๐Ÿ’… ADD HL,SP ๐Ÿ’…

Add the value in SP to HL.

Cycles: 2

Bytes: 1

Flags: See ADD HL,r16.

๐Ÿ’… ADD SP,e8 ๐Ÿ’…

Add the signed value e8 to SP.

Cycles: 4

Bytes: 2

Flags:

  • Z โ€” 0.
  • N โ€” 0.
  • H โ€” Set if overflow from bit 3.
  • C โ€” Set if overflow from bit 7.

๐Ÿ’… AND A,r8 ๐Ÿ’…

Set A to the bitwise AND between the value in r8 and A.

Cycles: 1

Bytes: 1

Flags:

  • Z โ€” Set if result is 0.
  • N โ€” 0.
  • H โ€” 1.
  • C โ€” 0.

๐Ÿ’… AND A,[HL] ๐Ÿ’…

Set A to the bitwise AND between the byte pointed to by HL and A.

Cycles: 2

Bytes: 1

Flags: See AND A,r8.

๐Ÿ’… AND A,n8 ๐Ÿ’…

Set A to the bitwise AND between the value n8 and A.

Cycles: 2

Bytes: 2

Flags: See AND A,r8.

๐Ÿ’… BIT u3,r8 ๐Ÿ’…

Test bit u3 in register r8, set the zero flag if bit not set.

Cycles: 2

Bytes: 2

Flags:

  • Z โ€” Set if the selected bit is 0.
  • N โ€” 0.
  • H โ€” 1.

๐Ÿ’… BIT u3,[HL] ๐Ÿ’…

Test bit u3 in the byte pointed by HL, set the zero flag if bit not set.

Cycles: 3

Bytes: 2

Flags: See BIT u3,r8.

๐Ÿ’… CALL n16 ๐Ÿ’…

Call address n16.

This pushes the address of the instruction after the CALL on the stack, such that RET can pop it later; then, it executes an implicit JP n16.

Cycles: 6

Bytes: 3

Flags: None affected.

๐Ÿ’… CALL cc,n16 ๐Ÿ’…

Call address n16 if condition cc is met.

Cycles: 6 taken / 3 untaken

Bytes: 3

Flags: None affected.

๐Ÿ’… CCF ๐Ÿ’…

Complement Carry Flag.

Cycles: 1

Bytes: 1

Flags:

  • N โ€” 0.
  • H โ€” 0.
  • C โ€” Inverted.

๐Ÿ’… CP A,r8 ๐Ÿ’…

ComPare the value in A with the value in r8.

This subtracts the value in r8 from A and sets flags accordingly, but discards the result.

Cycles: 1

Bytes: 1

Flags:

  • Z โ€” Set if result is 0.
  • N โ€” 1.
  • H โ€” Set if borrow from bit 4.
  • C โ€” Set if borrow (i.e. if r8 > A).

๐Ÿ’… CP A,[HL] ๐Ÿ’…

ComPare the value in A with the byte pointed to by HL.

This subtracts the byte pointed to by HL from A and sets flags accordingly, but discards the result.

Cycles: 2

Bytes: 1

Flags: See CP A,r8.

๐Ÿ’… CP A,n8 ๐Ÿ’…

ComPare the value in A with the value n8.

This subtracts the value n8 from A and sets flags accordingly, but discards the result.

Cycles: 2

Bytes: 2

Flags: See CP A,r8.

๐Ÿ’… CPL ๐Ÿ’…

ComPLement accumulator (A = ~A); also called bitwise NOT.

Cycles: 1

Bytes: 1

Flags:

  • N โ€” 1.
  • H โ€” 1.

๐Ÿ’… DAA ๐Ÿ’…

Decimal Adjust Accumulator.

Designed to be used after performing an arithmetic instruction (ADD, ADC, SUB, SBC) whose inputs were in Binary-Coded Decimal (BCD), adjusting the result to likewise be in BCD.

The exact behavior of this instruction depends on the state of the subtract flag N:

If the subtract flag N is set:

  1. Initialize the adjustment to 0.
  2. If the half-carry flag H is set, then add $6 to the adjustment.
  3. If the carry flag is set, then add $60 to the adjustment.
  4. Subtract the adjustment from A.

If the subtract flag N is not set:

  1. Initialize the adjustment to 0.
  2. If the half-carry flag H is set or A & $F > $9, then add $6 to the adjustment.
  3. If the carry flag is set or A > $99, then add $60 to the adjustment and set the carry flag.
  4. Add the adjustment to A.

Cycles: 1

Bytes: 1

Flags:

  • Z โ€” Set if result is 0.
  • H โ€” 0.
  • C โ€” Set or unaffected depending on the operation.

๐Ÿ’… DEC r8 ๐Ÿ’…

Decrement the value in register r8 by 1.

Cycles: 1

Bytes: 1

Flags:

  • Z โ€” Set if result is 0.
  • N โ€” 1.
  • H โ€” Set if borrow from bit 4.

๐Ÿ’… DEC [HL] ๐Ÿ’…

Decrement the byte pointed to by HL by 1.

Cycles: 3

Bytes: 1

Flags: See DEC r8.

๐Ÿ’… DEC r16 ๐Ÿ’…

Decrement the value in register r16 by 1.

Cycles: 2

Bytes: 1

Flags: None affected.

๐Ÿ’… DEC SP ๐Ÿ’…

Decrement the value in register SP by 1.

Cycles: 2

Bytes: 1

Flags: None affected.

๐Ÿ’… DI ๐Ÿ’…

Disable Interrupts by clearing the IME flag.

Cycles: 1

Bytes: 1

Flags: None affected.

๐Ÿ’… EI ๐Ÿ’…

Enable Interrupts by setting the IME flag.

The flag is only set after the instruction following EI.

Cycles: 1

Bytes: 1

Flags: None affected.

๐Ÿ’… HALT ๐Ÿ’…

Enter CPU low-power consumption mode until an interrupt occurs.

The exact behavior of this instruction depends on the state of the IME flag, and whether interrupts are pending (i.e. whether [IE] & [IF] is non-zero):

  • If the IME flag is set: The CPU enters low-power mode until after an interrupt is about to be serviced. The handler is executed normally, and the CPU resumes execution after the HALT when that returns.
  • If the IME flag is not set, and no interrupts are pending: As soon as an interrupt becomes pending, the CPU resumes execution. This is like the above, except that the handler is not called.

okay so picking up right where we left off inside HALT's whole situation:

If the IME flag is not set, and some interrupt is pending: the CPU continues execution after the HALT, but the byte after it is read twice in a row (PC is not incremented, due to a hardware bug).

not me reading the same byte twice because of a hardware bug ๐Ÿ˜ญ iconic behavior, honestly.
  • Cycles: -
  • Bytes: 1
  • Flags: none affected

INC r8

Bump the value in register r8 up by 1. Literally just +1 energy.

  • Cycles: 1
  • Bytes: 1
  • Flags:
    • Z โ€” set if result is 0.
    • N โ€” 0
    • H โ€” set if overflow from bit 3.

INC [HL]

Increment the byte pointed to by HL by 1. One little byte glow-up.

  • Cycles: 3
  • Bytes: 1
  • Flags: see INC r8.

INC r16

Increment the value in register r16 by 1.

  • Cycles: 2
  • Bytes: 1
  • Flags: none affected.

INC SP

Increment the value in register SP by 1. Stack pointer gets a little nudge.

  • Cycles: 2
  • Bytes: 1
  • Flags: none affected.

JP n16

Jump to address n16; basically copy n16 straight into PC. Main character relocation.

  • Cycles: 4
  • Bytes: 3
  • Flags: none affected.

JP cc,n16

Jump to address n16 only if condition cc is met. Conditional slay.

  • Cycles: 4 taken / 3 untaken
  • Bytes: 3
  • Flags: none affected.

JP HL

Jump to the address in HL; effectively copy the value in register HL into PC.

  • Cycles: 1
  • Bytes: 1
  • Flags: none affected.

JR n16

Relative Jump to address n16.

The target address n16 is encoded as a signed 8-bit offset from the address immediately following the JR instruction, so it must be between -128 and 127 bytes away. For example:

                 JR Label  ; no-op; encoded offset of 0
             Label:
                 JR Label  ; infinite loop; encoded offset of -2
  • Cycles: 3
  • Bytes: 2
  • Flags: none affected.

JR cc,n16

Relative Jump to address n16 if condition cc is met.

The target address n16 is encoded as a signed 8-bit offset from the address immediately following the JR instruction, so it must be between -128 and 127 bytes away.

  • Cycles: 3 taken / 2 untaken
  • Bytes: 2
  • Flags: none affected.

LD r8,r8

Copy (aka Load) the value in the register on the right into the register on the left.

Storing a register into itself is a no-op; however, some Game Boy emulators interpret LD B,B as a breakpoint, or LD D,D as a debug message (such as BGB: https://bgb.bircd.org/manual.html#expressions).

  • Cycles: 1
  • Bytes: 1
  • Flags: none affected.

LD r8,n8

Copy the value n8 into register r8.

  • Cycles: 2
  • Bytes: 2
  • Flags: none affected.

LD r16,n16

Copy the value n16 into register r16.

  • Cycles: 3
  • Bytes: 3
  • Flags: none affected.

LD [HL],r8

Copy the value in register r8 into the byte pointed to by HL.

  • Cycles: 2
  • Bytes: 1
  • Flags: none affected.

LD [HL],n8

Copy the value n8 into the byte pointed to by HL.

  • Cycles: 3
  • Bytes: 2
  • Flags: none affected.

LD r8,[HL]

Copy the value pointed to by HL into register r8.

  • Cycles: 2
  • Bytes: 1
  • Flags: none affected.

LD [r16],A

Copy the value in register A into the byte pointed to by r16.

  • Cycles: 2
  • Bytes: 1
  • Flags: none affected.

LD [n16],A

Copy the value in register A into the byte at address n16.

  • Cycles: 4
  • Bytes: 3
  • Flags: none affected.

LDH [n16],A

Copy the value in register A into the byte at address n16.

The destination address n16 is encoded as its 8-bit low byte and assumes a high byte of $FF, so it must be between $FF00 and $FFFF.

  • Cycles: 3
  • Bytes: 2
  • Flags: none affected.

LDH [C],A

Copy the value in register A into the byte at address $FF00+C.

  • Cycles: 2
  • Bytes: 1
  • Flags: none affected.

This is sometimes written as LD [$FF00+C],A.

LD A,[r16]

Copy the byte pointed to by r16 into register A.

  • Cycles: 2
  • Bytes: 1
  • Flags: none affected.

LD A,[n16]

Copy the byte at address n16 into register A.

  • Cycles: 4
  • Bytes: 3
  • Flags: none affected.

LDH A,[n16]

Copy the byte at address n16 into register A.

The source address n16 is encoded as its 8-bit low byte and assumes a high byte of $FF, so it must be between $FF00 and $FFFF.

  • Cycles: 3
  • Bytes: 2
  • Flags: none affected.

LDH A,[C]

Copy the byte at address $FF00+C into register A.

  • Cycles: 2
  • Bytes: 1
  • Flags: none affected.

This is sometimes written as LD A,[$FF00+C].

LD [HLI],A

Copy the value in register A into the byte pointed by HL and increment HL afterwards.

  • Cycles: 2
  • Bytes: 1
  • Flags: none affected.

This is sometimes written as LD [HL+],A, or LDI [HL],A.

LD [HLD],A

Copy the value in register A into the byte pointed by HL and decrement HL afterwards.

  • Cycles: 2
  • Bytes: 1
  • Flags: none affected.

This is sometimes written as LD [HL-],A, or LDD [HL],A.

LD A,[HLD]

Copy the byte pointed to by HL into register A, and decrement HL afterwards.

  • Cycles: 2
  • Bytes: 1
  • Flags: none affected.

This is sometimes written as LD A,[HL-], or LDD A,[HL].

LD A,[HLI]

Copy the byte pointed to by HL into register A, and increment HL afterwards.

  • Cycles: 2
  • Bytes: 1
  • Flags: none affected.

This is sometimes written as LD A,[HL+], or LDI A,[HL].

LD SP,n16

Copy the value n16 into register SP.

  • Cycles: 3
  • Bytes: 3
  • Flags: none affected.

LD [n16],SP

Copy SP & $FF to address n16 and SP >> 8 to address n16 + 1.

  • Cycles: 5
  • Bytes: 3
  • Flags: none affected.

LD HL,SP+e8

Add the signed value e8 to SP and copy the result in HL.

  • Cycles: 3
  • Bytes: 2
  • Flags:
    • Z โ€” 0
    • N โ€” 0
    • H โ€” set if overflow from bit 3.
    • C โ€” set if overflow from bit 7.

LD SP,HL

Copy register HL into register SP.

  • Cycles: 2
  • Bytes: 1
  • Flags: none affected.

NOP

No OPeration. The icon of doing absolutely nothing, periodt.

  • Cycles: 1
  • Bytes: 1
  • Flags: none affected.

OR A,r8

Set A to the bitwise OR between the value in r8 and A.

  • Cycles: 1
  • Bytes: 1
  • Flags:
    • Z โ€” set if result is 0.
    • N โ€” 0
    • H โ€” 0
    • C โ€” 0

OR A,[HL]

Set A to the bitwise OR between the byte pointed to by HL and A.

  • Cycles: 2
  • Bytes: 1
  • Flags: see OR A,r8.

OR A,n8

Set A to the bitwise OR between the value n8 and A.

  • Cycles: 2
  • Bytes: 2
  • Flags: see OR A,r8.

POP AF

Pop register AF from the stack. This is roughly equivalent to the following imaginary instructions:

LD F, [SP]  ; See below for individual flags
INC SP
LD A, [SP]
INC SP
  • Cycles: 3
  • Bytes: 1
  • Flags:
    • Z โ€” set from bit 7 of the popped low byte.
    • N โ€” set from bit 6 of the popped low byte.
    • H โ€” set from bit 5 of the popped low byte.
    • C โ€” set from bit 4 of the popped low byte.

POP r16

Pop register r16 from the stack. This is roughly equivalent to the following imaginary instructions:

LD LOW(r16), [SP]   ; C, E or L
INC SP
LD HIGH(r16), [SP]  ; B, D or H
INC SP
  • Cycles: 3
  • Bytes: 1
  • Flags: none affected.

PUSH AF

Push register AF into the stack. This is roughly equivalent to the following imaginary instructions:

DEC SP
LD [SP], A
DEC SP
LD [SP], F.Z << 7 | F.N << 6 | F.H << 5 | F.C << 4
  • Cycles: 4
  • Bytes: 1
  • Flags: none affected.

PUSH r16

Push register r16 into the stack. This is roughly equivalent to the following imaginary instructions:

DEC SP
LD [SP], HIGH(r16)  ; B, D or H
DEC SP
LD [SP], LOW(r16)   ; C, E or L
  • Cycles: 4
  • Bytes: 1
  • Flags: none affected.

RES u3,r8

Set bit u3 in register r8 to 0. Bit 0 is the rightmost one, bit 7 the leftmost one.

  • Cycles: 2
  • Bytes: 2
  • Flags: none affected.

RES u3,[HL]

Set bit u3 in the byte pointed by HL to 0. Bit 0 is the rightmost one, bit 7 the leftmost one.

  • Cycles: 4
  • Bytes: 2
  • Flags: none affected.

RET

Return from subroutine. This is basically a POP PC (if such an instruction existed). See POP r16 for an explanation of how POP works.

  • Cycles: 4
  • Bytes: 1
  • Flags: none affected.

RET cc

Return from subroutine if condition cc is met.

  • Cycles: 5 taken / 2 untaken
  • Bytes: 1
  • Flags: none affected.

RETI

Return from subroutine and enable interrupts. This is basically equivalent to executing EI then RET, meaning that IME is set right after this instruction.

  • Cycles: 4
  • Bytes: 1
  • Flags: none affected.

RL r8

Rotate bits in register r8 left, through the carry flag.

         โ”โ” Flags โ”โ”“ โ”โ”โ”โ”โ”โ”โ”โ” r8 โ”โ”โ”โ”โ”โ”โ”“
       โ”Œโ”€โ•‚โ”€   C   โ†โ•‚โ”€โ•‚โ”€ b7 โ† ... โ† b0 โ†โ•‚โ”€โ”
       โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Cycles: 2
  • Bytes: 2
  • Flags:
    • Z โ€” set if result is 0.
    • N โ€” 0
    • H โ€” 0
    • C โ€” set according to result.

RL [HL]

Rotate the byte pointed to by HL left, through the carry flag.

         โ”โ” Flags โ”โ”“ โ”โ”โ”โ”โ”โ”โ” [HL] โ”โ”โ”โ”โ”โ”“
       โ”Œโ”€โ•‚โ”€   C   โ†โ•‚โ”€โ•‚โ”€ b7 โ† ... โ† b0 โ†โ•‚โ”€โ”
       โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Cycles: 4
  • Bytes: 2
  • Flags: see RL r8.

RLA

Rotate register A left, through the carry flag.

         โ”โ” Flags โ”โ”“ โ”โ”โ”โ”โ”โ”โ”โ” A โ”โ”โ”โ”โ”โ”โ”โ”“
       โ”Œโ”€โ•‚โ”€   C   โ†โ•‚โ”€โ•‚โ”€ b7 โ† ... โ† b0 โ†โ•‚โ”€โ”
       โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Cycles: 1
  • Bytes: 1
  • Flags:
    • Z โ€” 0
    • N โ€” 0
    • H โ€” 0
    • C โ€” set according to result.

RLC r8

Rotate register r8 Left Circularly.

       โ”โ” Flags โ”โ”“   โ”โ”โ”โ”โ”โ”โ”โ” r8 โ”โ”โ”โ”โ”โ”โ”“
       โ”ƒ    C   โ†โ•‚โ”€โ”ฌโ”€โ•‚โ”€ b7 โ† ... โ† b0 โ†โ•‚โ”€โ”
       โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚
                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Cycles: 2
  • Bytes: 2
  • Flags:
    • Z โ€” set if result is 0.
    • N โ€” 0
    • H โ€” 0
    • C โ€” set according to result.

RLC [HL]

Rotate the byte pointed to by HL Left Circularly.

โ€ฆand the rest of the RLC [HL] entry wraps up with the little loop diagram, bestie ๐Ÿ’–

       โ”โ” Flags โ”โ”“   โ”โ”โ”โ”โ”โ”โ” [HL] โ”โ”โ”โ”โ”โ”“
       โ”ƒ    C   โ†โ•‚โ”€โ”ฌโ”€โ•‚โ”€ b7 โ† ... โ† b0 โ†โ•‚โ”€โ”
       โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚
                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Cycles: 4
  • Bytes: 2
  • Flags: See โ€œRLC r8โ€

๐ŸŒช๏ธ RLCA

Rotate register A Left Circularly โ€” the bit that falls off the top loops right back around, no carry nonsense involved ๐ŸŽ 

       โ”โ” Flags โ”โ”“   โ”โ”โ”โ”โ”โ”โ”โ” A โ”โ”โ”โ”โ”โ”โ”โ”“
       โ”ƒ    C   โ†โ•‚โ”€โ”ฌโ”€โ•‚โ”€ b7 โ† ... โ† b0 โ†โ•‚โ”€โ”
       โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚
                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Cycles: 1
  • Bytes: 1
  • Flags: Z = 0, N = 0, H = 0, C = set according to result. ๐Ÿ’ซ

๐ŸŒช๏ธ RR r8

Rotate register r8 right, through the carry flag โ€” so the old carry gets shoved into the top bit on its way round ๐Ÿ”„

         โ”โ”โ”โ”โ”โ”โ”โ” r8 โ”โ”โ”โ”โ”โ”โ”“ โ”โ” Flags โ”โ”“
       โ”Œโ”€โ•‚โ†’ b7 โ†’ ... โ†’ b0 โ”€โ•‚โ”€โ•‚โ†’   C   โ”€โ•‚โ”€โ”
       โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Cycles: 2
  • Bytes: 2
  • Flags: Z = set if result is 0, N = 0, H = 0, C = set according to result โœจ

๐ŸŒช๏ธ RR [HL]

Same rotation-through-carry energy as above, except it's the byte pointed to by HL getting the makeover, not a register ๐Ÿซถ

         โ”โ”โ”โ”โ”โ”โ” [HL] โ”โ”โ”โ”โ”โ”“ โ”โ” Flags โ”โ”“
       โ”Œโ”€โ•‚โ†’ b7 โ†’ ... โ†’ b0 โ”€โ•‚โ”€โ•‚โ†’   C   โ”€โ•‚โ”€โ”
       โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Cycles: 4
  • Bytes: 2
  • Flags: See โ€œRR r8โ€

๐ŸŒช๏ธ RRA

Rotate register A right, through the carry flag. A-only version, so it's a speedy little one-cycler ๐Ÿ˜Œ

         โ”โ”โ”โ”โ”โ”โ”โ” A โ”โ”โ”โ”โ”โ”โ”โ”“ โ”โ” Flags โ”โ”“
       โ”Œโ”€โ•‚โ†’ b7 โ†’ ... โ†’ b0 โ”€โ•‚โ”€โ•‚โ†’   C   โ”€โ•‚โ”€โ”
       โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Cycles: 1
  • Bytes: 1
  • Flags: Z = 0, N = 0, H = 0, C = set according to result โญ

๐ŸŽก RRC r8

Rotate register r8 Right Circularly โ€” straight-up loop, the carry flag is literally just watching ๐Ÿ‘€

         โ”โ”โ”โ”โ”โ”โ”โ” r8 โ”โ”โ”โ”โ”โ”โ”“   โ”โ” Flags โ”โ”“
       โ”Œโ”€โ•‚โ†’ b7 โ†’ ... โ†’ b0 โ”€โ•‚โ”€โ”ฌโ”€โ•‚โ†’   C    โ”ƒ
       โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”›
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Cycles: 2
  • Bytes: 2
  • Flags: Z = set if result is 0, N = 0, H = 0, C = set according to result ๐Ÿ’…

๐ŸŽก RRC [HL]

Rotate the byte pointed to by HL Right Circularly. Same circular vibe, memory flavour ๐ŸŒธ

         โ”โ”โ”โ”โ”โ”โ” [HL] โ”โ”โ”โ”โ”โ”“   โ”โ” Flags โ”โ”“
       โ”Œโ”€โ•‚โ†’ b7 โ†’ ... โ†’ b0 โ”€โ•‚โ”€โ”ฌโ”€โ•‚โ†’   C    โ”ƒ
       โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”›
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Cycles: 4
  • Bytes: 2
  • Flags: See โ€œRRC r8โ€

๐ŸŽก RRCA

Rotate register A Right Circularly. She's iconic, she's one byte, she's one cycle ๐ŸŽ€

         โ”โ”โ”โ”โ”โ”โ”โ” A โ”โ”โ”โ”โ”โ”โ”โ”“   โ”โ” Flags โ”โ”“
       โ”Œโ”€โ•‚โ†’ b7 โ†’ ... โ†’ b0 โ”€โ•‚โ”€โ”ฌโ”€โ•‚โ†’   C    โ”ƒ
       โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”‚ โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”›
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Cycles: 1
  • Bytes: 1
  • Flags: Z = 0, N = 0, H = 0, C = set according to result ๐ŸŒˆ

๐Ÿ“ž RST vec

Call address vec. This is a shorter and faster equivalent to โ€œCALLโ€ for suitable values of vec โ€” like the express-lane version of a call, no cap ๐Ÿ”ฅ

  • Cycles: 4
  • Bytes: 1
  • Flags: None affected.

โž– SBC A,r8

Subtract the value in r8 and the carry flag from A โ€” yes, the carry jumps in too, that's literally the whole point ๐Ÿ™ˆ

  • Cycles: 1
  • Bytes: 1
  • Flags:
    • Z = set if result is 0
    • N = 1
    • H = set if borrow from bit 4
    • C = set if borrow (i.e. if (r8 + carry) > A)

โž– SBC A,[HL]

Subtract the byte pointed to by HL and the carry flag from A ๐Ÿงฎ

  • Cycles: 2
  • Bytes: 1
  • Flags: See โ€œSBC A,r8โ€

โž– SBC A,n8

Subtract the value n8 and the carry flag from A ๐Ÿงฎ

  • Cycles: 2
  • Bytes: 2
  • Flags: See โ€œSBC A,r8โ€

๐Ÿšฉ SCF

Set Carry Flag. That's it, that's the whole instruction, and honestly? Slay ๐Ÿ’…

  • Cycles: 1
  • Bytes: 1
  • Flags: N = 0, H = 0, C = 1 (notice Z doesn't even get a mention here ๐Ÿ‘€)

๐Ÿ”ง SET u3,r8

Set bit u3 in register r8 to 1. Bit 0 is the rightmost one, bit 7 the leftmost one โ€” write that down bestie, it comes up constantly ๐Ÿ“

  • Cycles: 2
  • Bytes: 2
  • Flags: None affected.

๐Ÿ”ง SET u3,[HL]

Set bit u3 in the byte pointed by HL to 1. Bit 0 is the rightmost one, bit 7 the leftmost one โœจ

  • Cycles: 4
  • Bytes: 2
  • Flags: None affected.

โฌ…๏ธ SLA r8

Shift Left Arithmetically register r8 โ€” a 0 slides in at the bottom, everything marches left, the top bit exits into the carry ๐Ÿšช

       โ”โ” Flags โ”โ”“ โ”โ”โ”โ”โ”โ”โ”โ” r8 โ”โ”โ”โ”โ”โ”โ”“
       โ”ƒ    C   โ†โ•‚โ”€โ•‚โ”€ b7 โ† ... โ† b0 โ†โ•‚โ”€ 0
       โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”›
  • Cycles: 2
  • Bytes: 2
  • Flags: Z = set if result is 0, N = 0, H = 0, C = set according to result ๐Ÿฆ‹

โฌ…๏ธ SLA [HL]

Shift Left Arithmetically the byte pointed to by HL. Same leftward march, memory edition ๐Ÿ’พ

       โ”โ” Flags โ”โ”“ โ”โ”โ”โ”โ”โ”โ” [HL] โ”โ”โ”โ”โ”โ”“
       โ”ƒ    C   โ†โ•‚โ”€โ•‚โ”€ b7 โ† ... โ† b0 โ†โ•‚โ”€ 0
       โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”›
  • Cycles: 4
  • Bytes: 2
  • Flags: See โ€œSLA r8โ€

โžก๏ธ SRA r8

Shift Right Arithmetically register r8 โ€” and heads up, bit 7 of r8 is unchanged, it just duplicates itself like a vibe check ๐Ÿงš

       โ”โ”โ”โ”โ”โ”โ” r8 โ”โ”โ”โ”โ”โ”โ”“ โ”โ” Flags โ”โ”“
       โ”ƒ b7 โ†’ ... โ†’ b0 โ”€โ•‚โ”€โ•‚โ†’   C    โ”ƒ
       โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”›
  • Cycles: 2
  • Bytes: 2
  • Flags: Z = set if result is 0, N = 0, H = 0, C = set according to result ๐Ÿ’œ

โžก๏ธ SRA [HL]

Shift Right Arithmetically the byte pointed to by HL โ€” and again, bit 7 of the byte pointed to by HL is unchanged ๐Ÿซง

       โ”โ”โ”โ”โ”โ” [HL] โ”โ”โ”โ”โ”โ”“ โ”โ” Flags โ”โ”“
       โ”ƒ b7 โ†’ ... โ†’ b0 โ”€โ•‚โ”€โ•‚โ†’   C    โ”ƒ
       โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”›
  • Cycles: 4
  • Bytes: 2
  • Flags: See โ€œSRA r8โ€

โžก๏ธ SRL r8

Shift Right Logically register r8 โ€” unlike SRA, a big fat 0 slides in at the top, so no sign-preserving behaviour here ๐Ÿ•ณ๏ธ

          โ”โ”โ”โ”โ”โ”โ”โ” r8 โ”โ”โ”โ”โ”โ”โ”“ โ”โ” Flags โ”โ”“
       0 โ”€โ•‚โ†’ b7 โ†’ ... โ†’ b0 โ”€โ•‚โ”€โ•‚โ†’   C    โ”ƒ
          โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”›
  • Cycles: 2
  • Bytes: 2
  • Flags: Z = set if result is 0, N = 0, H = 0, C = set according to result ๐ŸŒŸ

โžก๏ธ SRL [HL]

Shift Right Logically the byte pointed to by HL ๐Ÿ•ณ๏ธ

          โ”โ”โ”โ”โ”โ”โ” [HL] โ”โ”โ”โ”โ”โ”“ โ”โ” Flags โ”โ”“
       0 โ”€โ•‚โ†’ b7 โ†’ ... โ†’ b0 โ”€โ•‚โ”€โ•‚โ†’   C    โ”ƒ
          โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”›
  • Cycles: 4
  • Bytes: 2
  • Flags: See โ€œSRL r8โ€

๐Ÿ˜ด STOP

Enter CPU very low power mode. Also used to switch between GBC double speed and normal speed CPU modes โ€” she does double duty, main character energy fr ๐Ÿ‘‘

๐Ÿšจ okay, listen: the exact behavior of this instruction is fragile, and it may interpret its second byte as a separate instruction (see the Pan Docs: https://gbdev.io/pandocs/Reducing_Power_Consumption.html#using-the-stop-instruction). That's why rgbasm(1) allows explicitly specifying the second byte (STOP n8) to override the default of $00 (a NOP instruction). Don't just assume it's chill ๐Ÿ’€
  • Cycles: -
  • Bytes: 2
  • Flags: None affected.

โž– SUB A,r8

Subtract the value in r8 from A. No carry shenanigans, just straight subtraction ๐Ÿ”ป

  • Cycles: 1
  • Bytes: 1
  • Flags:
    • Z = set if result is 0
    • N = 1
    • H = set if borrow from bit 4
    • C = set if borrow (i.e. if r8 > A)

โž– SUB A,[HL]

Subtract the byte pointed to by HL from A ๐Ÿ”ป

  • Cycles: 2
  • Bytes: 1
  • Flags: See โ€œSUB A,r8โ€

โž– SUB A,n8

Subtract the value n8 from A ๐Ÿ”ป

  • Cycles: 2
  • Bytes: 2
  • Flags: See โ€œSUB A,r8โ€

๐Ÿ”€ SWAP r8

Swap the upper 4 bits in register r8 and the lower 4 ones. Nibble exchange, very demure, very mindful ๐ŸŽ€

  • Cycles: 2
  • Bytes: 2
  • Flags: Z = set if result is 0, N = 0, H = 0, C = 0

๐Ÿ”€ SWAP [HL]

Swap the upper 4 bits in the byte pointed by HL and the lower 4 ones ๐ŸŽ€

  • Cycles: 4
  • Bytes: 2
  • Flags: See โ€œSWAP r8โ€

๐Ÿง  XOR A,r8

Set A to the bitwise XOR between the value in r8 and A โšก

  • Cycles: 1
  • Bytes: 1
  • Flags: Z = set if result is 0, N = 0, H = 0, C = 0

๐Ÿง  XOR A,[HL]

Set A to the bitwise XOR between the byte pointed to by HL and A โšก

  • Cycles: 2
  • Bytes: 1
  • Flags: See โ€œXOR A,r8โ€

๐Ÿง  XOR A,n8

Set A to the bitwise XOR between the value n8 and A โšก

  • Cycles: 2
  • Bytes: 2
  • Flags: See โ€œXOR A,r8โ€

๐Ÿ‘€ SEE ALSO ๐Ÿ‘‘


๐Ÿ“œ HISTORY ๐Ÿ•ฐ๏ธ

rgbasm(1) was originally written by Carsten Sรธrensen as part of the ASMotor package, and was later repackaged in RGBDS by Justin Lloyd. It is now maintained by a number of contributors at https://github.com/gbdev/rgbds โ€” go say hi to the maintainers, they're lowkey carrying the whole toolchain ๐Ÿซถ๐Ÿ’–


and that's the whole page, bestie!! ๐Ÿ’…โœจ๐ŸŽ€ shoutout to the Debian packagers for shipping this on September 22, 2026, and to GBZ80(7) herself for being the most iconic instruction set doc in the game. now go write some assembly, you absolute legend ๐Ÿ‘‘๐ŸŒธ๐Ÿฆ‹

๐Ÿ“ฆ where this page comes from