Skip to main content

gameboy_rom/
opcodes.rs

1//! Types related to the opcodes of the Gameboy parser.
2
3/// An 8 bit register.
4///
5/// Includes the `DerefHL` variant which represents a memory access at the value
6/// contained in the `HL` 16 bit register.
7#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
8pub enum Register8 {
9    A,
10    B,
11    C,
12    D,
13    E,
14    H,
15    L,
16    DerefHL,
17}
18
19/// A 16 bit register.
20///
21/// Does not include `PC`, the program counter, used to indicate which
22/// instruction is being executed next.
23#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
24pub enum Register16 {
25    /// 16 bit register that's made up of 2 8 bit registers, `B` and `C`.
26    BC,
27    /// 16 bit register that's made up of 2 8 bit registers, `D` and `E`.
28    DE,
29    /// 16 bit register that's made up of 2 8 bit registers, `H` and `L`.
30    HL,
31    /// 16 bit register that's made up of 2 8 bit registers, `A` and `F`.
32    AF,
33    /// The stack pointer.
34    SP,
35}
36
37/// Flags relevant to the operation of the instruction.
38///
39/// This flag is used to specify which flag the Opcode cares about, it is not
40/// used to indicate which flags an instruction may set.
41///
42/// For example, `Opcode::Jp(Some(Flag::NZ), 0x1234)` says that the instruction
43/// is a `Jp` (jump) instruction that will jump to location 0x1234, if the `NZ`
44/// (not zero) flag is set.
45#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
46pub enum Flag {
47    /// The Carry flag.
48    C,
49    /// The Zero Flag.
50    Z,
51    /// The inverse of the Carry flag.
52    NC,
53    /// The inverse of the Zero flag.
54    NZ,
55}
56
57/// The instructions of the Gameboy.
58///
59/// The naming tends to be of the form: `ActionDestSrc` when there is ambiguity.
60///
61/// For example, `Opcode::StoreImm16AddrSp` means that the `SP` register should
62/// be stored at the address specified by the immediate 16 bit value.
63///
64/// These docs don't intend to include complete explanations of the instructions,
65/// though the comments below may provide a basic overview.
66#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
67pub enum Opcode {
68    /// No operation.
69    Nop,
70    /// The Gameboy enters a very low-power STOP state, graphics will not continue to draw.
71    Stop,
72    /// The Gameboy enters a low-power HALT state.
73    Halt,
74    /// Store an immediate value into a 16 bit register.
75    StoreImm16(Register16, u16),
76    /// Store an immediate value into an 8 bit register.
77    StoreImm8(Register8, u8),
78    /// Store A at (HL) and increment or decrement HL; true means inc
79    StoreAToHlAddr(bool),
80    /// Load A from (HL) and increment or decrement HL; true means inc
81    LoadAFromHlAddr(bool),
82    /// Store A to the value pointed at by register 16 (must be BC or DE)
83    StoreATo16(Register16),
84    /// Loads A from value pointed at by register 16 (must be BC or DE)
85    LoadAFromReg16Addr(Register16),
86    Mov8(Register8, Register8),
87    /// Relative jump based on flag to offset
88    Jr(Option<Flag>, u8),
89    /// Jump based on flag to offset
90    Jp(Option<Flag>, u16),
91    /// Increment an 8 bit regsiter.
92    Inc8(Register8),
93    /// Decrement an 8 bit regsiter.
94    Dec8(Register8),
95    /// Increment a 16 bit regsiter.
96    Inc16(Register16),
97    /// Decrement a 16 bit regsiter.
98    Dec16(Register16),
99    /// Push the value in the given register onto the stack.
100    Push(Register16),
101    /// Pop a value off the stack and load it into the given register.
102    Pop(Register16),
103    /// Add the given regsiter to the A.
104    Add(Register8),
105    /// Add the given regsiter to the A with carry.
106    Adc(Register8),
107    /// Subtract the given regsiter from the A.
108    Sub(Register8),
109    /// Subtract the given regsiter from the A with carry.
110    Sbc(Register8),
111    /// Bitwise AND the given register with the A.
112    And(Register8),
113    /// Bitwise XOR the given register with the A.
114    Xor(Register8),
115    /// Bitwise OR the given register with the A.
116    Or(Register8),
117    /// Compare the value of the given register with the A and set flags.
118    Cp(Register8),
119    /// Add an immediate value to the A.
120    Add8(u8),
121    /// Add an immediate value to the A with carry.
122    Adc8(u8),
123    /// Subtract an immediate value from the A.
124    Sub8(u8),
125    /// Subtract an immediate value from the A with carry.
126    Sbc8(u8),
127    /// Bitwise AND an immediate value with the A.
128    And8(u8),
129    /// Bitwise XOR an immediate value with the A.
130    Xor8(u8),
131    /// Bitwise OR an immediate value with the A.
132    Or8(u8),
133    /// Compare the immediate value with the A and set flags.
134    Cp8(u8),
135    /// Add the immediate value to the Program Counter and load it into SP.
136    /// TODO: check this explanation
137    AddSp8(u8),
138    /// Converts the value in A to its BCD form.
139    /// TODO: double check this
140    Daa,
141    /// TODO: document this
142    Scf,
143    /// Bitwise negate the value in the A.
144    Cpl,
145    /// TODO: document this (inverse of SCF?)
146    Ccf,
147    /// Rotate A left.
148    Rlca,
149    /// Rotate A left through carry.
150    Rla,
151    /// Rotate A right.
152    Rrca,
153    /// Rotate A right through carry.
154    Rra,
155    /// Stores SP at pointer given by immediate 16.
156    StoreImm16AddrSp(u16),
157    /// Adds a value to HL.
158    AddHl(Register16),
159    /// Conditionally adjusts the program counter and updates the stack pointer.
160    Ret(Option<Flag>),
161    /// Non-conditional `Ret` that also enables interrupts.
162    Reti,
163    /// Disable interrupts.
164    Di,
165    /// Enable interrupts.
166    Ei,
167    /// Conditionally update push the program counter onto the stack and adjusts
168    /// the program counter.
169    Call(Option<Flag>, u16),
170    /// Gets the value at memory address HL and jumps to it.
171    JpHl,
172    /// Contains eight possible values: between 0-8. Value should be multplied
173    /// by 8 to determine the reset location.
174    /// TODO: consider simplifying this
175    Rst(u8),
176    /// HL = SP + (PC + i8).
177    /// TODO: double check behavior of relative parameters.
178    LdHlSp8(i8),
179    /// Load the value of HL into SP.
180    LdSpHl,
181    /// stores A in (u8)
182    StoreHA(u8),
183    /// loads A from (u8)
184    LoadHA(u8),
185    /// stores A in (C)
186    StoreCA,
187    /// Loads A from (C)
188    LoadCA,
189    /// LD (a16), A
190    StoreAAtAddress(u16),
191    /// LD A, (a16)
192    LoadAFromAddress(u16),
193    /// # 0xCB instructions
194    ///
195    /// Rotate register left.
196    Rlc(Register8),
197    /// Rotate register right.
198    Rrc(Register8),
199    /// Rotate register right through carry.
200    Rr(Register8),
201    /// Rotate register left through carry.
202    Rl(Register8),
203    /// Arithmetic left shift on given register.
204    Sla(Register8),
205    /// Arithmetic right shift on given register.
206    Sra(Register8),
207    /// Swap low and high nibble (4 bits).
208    Swap(Register8),
209    /// Logical Right shift on given register.
210    Srl(Register8),
211    /// Set flags based on the given bit in register.
212    /// u8 is number between 0 and 7 (inclusive).
213    Bit(u8, Register8),
214    /// Reset the given bit in the register.
215    /// u8 is number between 0 and 7 (inclusive)
216    Res(u8, Register8),
217    /// Set the given bit in the register.
218    /// u8 is number between 0 and 7 (inclusive)
219    Set(u8, Register8),
220}