mizu_core/
cpu.rs

1pub mod instruction;
2mod instructions_table;
3
4use bitflags::bitflags;
5use save_state::Savable;
6
7use crate::memory::InterruptType;
8use crate::GameBoyConfig;
9use instruction::{Condition, Instruction, Opcode, OperandType};
10
11pub trait CpuBusProvider {
12    fn read(&mut self, addr: u16) -> u8;
13    fn write(&mut self, addr: u16, data: u8);
14
15    fn take_next_interrupt(&mut self) -> Option<InterruptType>;
16    fn peek_next_interrupt(&mut self) -> Option<InterruptType>;
17
18    fn is_hdma_running(&mut self) -> bool;
19
20    fn enter_stop_mode(&mut self);
21    fn stopped(&self) -> bool;
22
23    /// Triggers oam_bug without clock, this is used for inc/dec instructions
24    fn trigger_write_oam_bug(&mut self, addr: u16);
25    /// Triggers oam_bug special case read_write, this happens when an
26    /// increment/decrement happen in the same cycle as read
27    fn trigger_read_write_oam_bug(&mut self, addr: u16);
28    /// reads data without triggering oam_bug, this is used in pop
29    fn read_no_oam_bug(&mut self, addr: u16) -> u8;
30}
31
32const INTERRUPTS_VECTOR: [u16; 5] = [0x40, 0x48, 0x50, 0x58, 0x60];
33
34#[derive(Copy, Clone, Debug, PartialEq)]
35pub struct CpuRegisters {
36    pub a: u8,
37    pub b: u8,
38    pub c: u8,
39    pub d: u8,
40    pub e: u8,
41    pub f: u8,
42    pub h: u8,
43    pub l: u8,
44    pub sp: u16,
45    pub pc: u16,
46}
47
48#[derive(Clone, Copy, Debug, PartialEq)]
49pub enum RunError {
50    IllegalInstruction
51}
52
53#[derive(Clone, Copy, Debug, PartialEq)]
54pub enum CpuState {
55    Normal,
56    InfiniteLoop,
57    Halting,
58    RunningHDMA,
59    Stopped,
60    RunningInterrupt(InterruptType),
61    Breakpoint(CpuRegisters),
62}
63
64bitflags! {
65    #[derive(Default, Savable)]
66    #[savable(bitflags)]
67    struct CpuFlags: u8 {
68        const Z = 1 << 7;
69        const N = 1 << 6;
70        const H = 1 << 5;
71        const C = 1 << 4;
72    }
73}
74
75#[derive(Default, Savable, PartialEq)]
76enum HaltMode {
77    #[default]
78    NotHalting,
79    HaltRunInterrupt,
80    HaltNoRunInterrupt,
81    HaltBug,
82}
83
84#[derive(Default, Savable)]
85pub struct Cpu {
86    pub reg_a: u8,
87    pub reg_b: u8,
88    pub reg_c: u8,
89    pub reg_d: u8,
90    pub reg_e: u8,
91    pub reg_h: u8,
92    pub reg_l: u8,
93    reg_f: CpuFlags,
94
95    pub reg_sp: u16,
96
97    pub reg_pc: u16,
98
99    enable_interrupt_next: bool,
100    ime: bool,
101    halt_mode: HaltMode,
102
103    config: GameBoyConfig,
104}
105
106impl Cpu {
107    pub fn new(config: GameBoyConfig) -> Self {
108        Self {
109            reg_a: 0,
110            reg_b: 0,
111            reg_c: 0,
112            reg_d: 0,
113            reg_e: 0,
114            reg_h: 0,
115            reg_l: 0,
116            reg_f: CpuFlags::from_bits_truncate(0),
117            reg_sp: 0,
118            reg_pc: 0,
119
120            enable_interrupt_next: false,
121            ime: false,
122            halt_mode: HaltMode::NotHalting,
123
124            config,
125        }
126    }
127
128    /// create a new cpu, with states that match the ones the CPU would have
129    /// if the boot-rom would run (default values for registers)
130    pub fn new_without_boot_rom(config: GameBoyConfig, is_cart_cgb: bool) -> Self {
131        let mut cpu = Self::new(config);
132
133        if cpu.config.is_dmg {
134            // initial values of the registers (DMG)
135            cpu.reg_af_write(0x01B0);
136            cpu.reg_bc_write(0x0013);
137            cpu.reg_de_write(0x00D8);
138            cpu.reg_hl_write(0x014D);
139        } else {
140            // initial values of the registers (CGB) for CGB games
141            // common
142            cpu.reg_af_write(0x1180);
143            cpu.reg_bc_write(0x0000);
144            if is_cart_cgb {
145                cpu.reg_de_write(0xFF56);
146                cpu.reg_hl_write(0x000D);
147            } else {
148                // initial values of the registers (CGB) for DMG games
149                cpu.reg_de_write(0x0008);
150                cpu.reg_hl_write(0x007C);
151            }
152        }
153        cpu.reg_sp = 0xFFFE;
154        cpu.reg_pc = 0x0100;
155
156        cpu
157    }
158
159    pub fn next_instruction<P: CpuBusProvider>(&mut self, bus: &mut P) -> Result<CpuState, RunError> {
160        if bus.stopped() {
161            self.advance_bus(bus);
162            return Ok(CpuState::Stopped);
163        }
164
165        if bus.is_hdma_running() {
166            self.advance_bus(bus);
167            return Ok(CpuState::RunningHDMA);
168        }
169
170        if self.halt_mode == HaltMode::HaltRunInterrupt
171            || self.halt_mode == HaltMode::HaltNoRunInterrupt
172        {
173            self.advance_bus(bus);
174
175            if bus.peek_next_interrupt().is_some() {
176                self.halt_mode = HaltMode::NotHalting;
177
178                if !self.config.is_dmg {
179                    self.advance_bus(bus);
180                }
181            } else {
182                return Ok(CpuState::Halting);
183            }
184        }
185
186        if self.ime && bus.peek_next_interrupt().is_some() {
187            let mut cpu_state = CpuState::Normal;
188
189            let pc = self.reg_pc;
190
191            // Push PC part 1
192            // trigger write oam bug because of the increment
193            bus.trigger_write_oam_bug(self.reg_sp);
194            self.reg_sp = self.reg_sp.wrapping_sub(1);
195            bus.write(self.reg_sp, (pc >> 8) as u8);
196
197            if let Some(int_type) = bus.take_next_interrupt() {
198                cpu_state = CpuState::RunningInterrupt(int_type);
199                self.reg_pc = INTERRUPTS_VECTOR[int_type as usize];
200            } else {
201                // Interrupt cancelled
202                self.reg_pc = 0;
203            }
204
205            self.ime = false;
206
207            // Push PC part 2
208            self.reg_sp = self.reg_sp.wrapping_sub(1);
209            bus.write(self.reg_sp, pc as u8);
210
211            // delay for interrupt
212            self.advance_bus(bus);
213            self.advance_bus(bus);
214            self.advance_bus(bus);
215            return Ok(cpu_state);
216        }
217
218        if self.enable_interrupt_next {
219            self.ime = true;
220            self.enable_interrupt_next = false;
221        }
222
223        let pc = self.reg_pc;
224        let mut instruction = Instruction::from_byte(self.fetch_next_pc(bus), pc);
225
226        if self.halt_mode == HaltMode::HaltBug {
227            self.halt_mode = HaltMode::NotHalting;
228            // do not add pc from the last fetch ^
229            self.reg_pc = pc;
230        }
231
232        if instruction.opcode == Opcode::Prefix {
233            instruction = Instruction::from_prefix(self.fetch_next_pc(bus), pc);
234        }
235
236        match self.exec_instruction(instruction, bus) {
237            Err(e) => {
238                // do not add pc from the last fetch ^
239                self.reg_pc = pc;
240                Err(e)
241            }
242            Ok(r) => Ok(r)
243        }
244    }
245}
246
247impl Cpu {
248    #[inline]
249    fn reg_af_read(&self) -> u16 {
250        (self.reg_a as u16) << 8 | self.reg_f.bits() as u16
251    }
252
253    #[inline]
254    fn reg_bc_read(&self) -> u16 {
255        (self.reg_b as u16) << 8 | self.reg_c as u16
256    }
257
258    #[inline]
259    fn reg_de_read(&self) -> u16 {
260        (self.reg_d as u16) << 8 | self.reg_e as u16
261    }
262
263    #[inline]
264    fn reg_hl_read(&self) -> u16 {
265        (self.reg_h as u16) << 8 | self.reg_l as u16
266    }
267
268    #[inline]
269    fn reg_af_write(&mut self, data: u16) {
270        self.reg_a = (data >> 8) as u8;
271        self.reg_f = CpuFlags::from_bits_truncate(data as u8);
272    }
273
274    #[inline]
275    fn reg_bc_write(&mut self, data: u16) {
276        self.reg_b = (data >> 8) as u8;
277        self.reg_c = data as u8;
278    }
279
280    #[inline]
281    fn reg_de_write(&mut self, data: u16) {
282        self.reg_d = (data >> 8) as u8;
283        self.reg_e = data as u8;
284    }
285
286    #[inline]
287    fn reg_hl_write(&mut self, data: u16) {
288        self.reg_h = (data >> 8) as u8;
289        self.reg_l = data as u8;
290    }
291
292    #[inline]
293    fn flag_get(&self, flag: CpuFlags) -> bool {
294        self.reg_f.intersects(flag)
295    }
296
297    #[inline]
298    fn flag_set(&mut self, flag: CpuFlags, value: bool) {
299        self.reg_f.set(flag, value);
300    }
301
302    fn registers(&self) -> CpuRegisters {
303        CpuRegisters {
304            a: self.reg_a,
305            b: self.reg_b,
306            c: self.reg_c,
307            d: self.reg_d,
308            e: self.reg_e,
309            f: self.reg_f.bits(),
310            h: self.reg_h,
311            l: self.reg_l,
312            sp: self.reg_sp,
313            pc: self.reg_pc,
314        }
315    }
316
317    fn fetch_next_pc<P: CpuBusProvider>(&mut self, bus: &mut P) -> u8 {
318        let result = bus.read(self.reg_pc);
319        bus.trigger_read_write_oam_bug(self.reg_pc);
320        self.reg_pc = self.reg_pc.wrapping_add(1);
321        result
322    }
323
324    fn read_operand<P: CpuBusProvider>(&mut self, ty: OperandType, bus: &mut P) -> u16 {
325        match ty {
326            OperandType::RegA => self.reg_a as u16,
327            OperandType::RegB => self.reg_b as u16,
328            OperandType::RegC => self.reg_c as u16,
329            OperandType::RegD => self.reg_d as u16,
330            OperandType::RegE => self.reg_e as u16,
331            OperandType::RegH => self.reg_h as u16,
332            OperandType::RegL => self.reg_l as u16,
333            OperandType::AddrHL => bus.read(self.reg_hl_read()) as u16,
334            OperandType::AddrHLDec => {
335                let hl = self.reg_hl_read();
336                let result = bus.read(hl) as u16;
337                bus.trigger_read_write_oam_bug(hl);
338                self.reg_hl_write(hl.wrapping_sub(1));
339                result
340            }
341            OperandType::AddrHLInc => {
342                let hl = self.reg_hl_read();
343                let result = bus.read(hl) as u16;
344                bus.trigger_read_write_oam_bug(hl);
345                self.reg_hl_write(hl.wrapping_add(1));
346                result
347            }
348            OperandType::AddrBC => bus.read(self.reg_bc_read()) as u16,
349            OperandType::AddrDE => bus.read(self.reg_de_read()) as u16,
350            OperandType::RegAF => self.reg_af_read(),
351            OperandType::RegBC => self.reg_bc_read(),
352            OperandType::RegDE => self.reg_de_read(),
353            OperandType::RegHL => self.reg_hl_read(),
354            OperandType::RegSP => self.reg_sp,
355            OperandType::Imm8 => self.fetch_next_pc(bus) as u16,
356            OperandType::Imm8Signed => self.fetch_next_pc(bus) as i8 as i16 as u16,
357            OperandType::Imm16 => {
358                (self.fetch_next_pc(bus) as u16) | ((self.fetch_next_pc(bus) as u16) << 8)
359            }
360            OperandType::HighAddr8 => {
361                let addr = 0xFF00 | self.fetch_next_pc(bus) as u16;
362                bus.read(addr) as u16
363            }
364            OperandType::HighAddrC => bus.read(0xFF00 | self.reg_c as u16) as u16,
365            OperandType::Addr16 => {
366                let addr =
367                    (self.fetch_next_pc(bus) as u16) | ((self.fetch_next_pc(bus) as u16) << 8);
368                bus.read(addr) as u16
369            }
370            OperandType::Implied => 0,
371            OperandType::Addr16Val16 => unreachable!(),
372        }
373    }
374
375    fn write_operand<P: CpuBusProvider>(&mut self, ty: OperandType, data: u16, bus: &mut P) {
376        match ty {
377            OperandType::RegA => self.reg_a = data as u8,
378            OperandType::RegB => self.reg_b = data as u8,
379            OperandType::RegC => self.reg_c = data as u8,
380            OperandType::RegD => self.reg_d = data as u8,
381            OperandType::RegE => self.reg_e = data as u8,
382            OperandType::RegH => self.reg_h = data as u8,
383            OperandType::RegL => self.reg_l = data as u8,
384            OperandType::AddrHL => bus.write(self.reg_hl_read(), data as u8),
385            OperandType::AddrHLDec => {
386                let hl = self.reg_hl_read();
387                bus.write(hl, data as u8);
388                self.reg_hl_write(hl.wrapping_sub(1));
389            }
390            OperandType::AddrHLInc => {
391                let hl = self.reg_hl_read();
392                bus.write(hl, data as u8);
393                self.reg_hl_write(hl.wrapping_add(1));
394            }
395            OperandType::AddrBC => bus.write(self.reg_bc_read(), data as u8),
396            OperandType::AddrDE => bus.write(self.reg_de_read(), data as u8),
397            OperandType::RegAF => self.reg_af_write(data),
398            OperandType::RegBC => self.reg_bc_write(data),
399            OperandType::RegDE => self.reg_de_write(data),
400            OperandType::RegHL => self.reg_hl_write(data),
401            OperandType::RegSP => self.reg_sp = data,
402            OperandType::HighAddr8 => {
403                let addr = 0xFF00 | self.fetch_next_pc(bus) as u16;
404                bus.write(addr, data as u8);
405            }
406            OperandType::HighAddrC => bus.write(0xFF00 | self.reg_c as u16, data as u8),
407            OperandType::Addr16 => {
408                let addr =
409                    (self.fetch_next_pc(bus) as u16) | ((self.fetch_next_pc(bus) as u16) << 8);
410                bus.write(addr, data as u8);
411            }
412            OperandType::Addr16Val16 => {
413                let addr =
414                    (self.fetch_next_pc(bus) as u16) | ((self.fetch_next_pc(bus) as u16) << 8);
415                bus.write(addr, data as u8);
416                bus.write(addr.wrapping_add(1), (data >> 8) as u8);
417            }
418            OperandType::Implied => {}
419            OperandType::Imm16 | OperandType::Imm8 | OperandType::Imm8Signed => unreachable!(),
420        }
421    }
422
423    /// advances the bus and all other components by one machine cycle
424    fn advance_bus<P: CpuBusProvider>(&mut self, bus: &mut P) {
425        bus.read(0);
426    }
427
428    pub fn stack_push<P: CpuBusProvider>(&mut self, data: u16, bus: &mut P) {
429        bus.trigger_write_oam_bug(self.reg_sp);
430        self.reg_sp = self.reg_sp.wrapping_sub(1);
431        bus.write(self.reg_sp, (data >> 8) as u8);
432        self.reg_sp = self.reg_sp.wrapping_sub(1);
433        bus.write(self.reg_sp, data as u8);
434    }
435
436    pub fn stack_pop<P: CpuBusProvider>(&mut self, bus: &mut P) -> u16 {
437        let low = bus.read_no_oam_bug(self.reg_sp);
438        // instead of triggering normal read oam bug, a glitch happen and
439        // read and write (because of increment) oam bug happen at the same
440        // cycle which produce a strange behaviour (impleented in read_write
441        // oam bug)
442        bus.trigger_read_write_oam_bug(self.reg_sp);
443
444        self.reg_sp = self.reg_sp.wrapping_add(1);
445        let high = bus.read(self.reg_sp);
446        self.reg_sp = self.reg_sp.wrapping_add(1);
447
448        ((high as u16) << 8) | low as u16
449    }
450
451    fn check_cond(&self, cond: Condition) -> bool {
452        match cond {
453            Condition::NC => !self.flag_get(CpuFlags::C),
454            Condition::C => self.flag_get(CpuFlags::C),
455            Condition::NZ => !self.flag_get(CpuFlags::Z),
456            Condition::Z => self.flag_get(CpuFlags::Z),
457            Condition::Unconditional => true,
458        }
459    }
460
461    fn exec_instruction<P: CpuBusProvider>(
462        &mut self,
463        instruction: Instruction,
464        bus: &mut P,
465    ) -> Result<CpuState, RunError> {
466        let src = self.read_operand(instruction.src, bus);
467
468        let mut cpu_state = CpuState::Normal;
469
470        let result = match instruction.opcode {
471            Opcode::Nop => Ok(0),
472            Opcode::Ld => Ok(src),
473            Opcode::LdBB => {
474                // self.reg_b = self.reg_b;
475                println!("Break point at {:04X} was hit", instruction.pc);
476
477                cpu_state = CpuState::Breakpoint(self.registers());
478
479                Ok(0)
480            }
481            Opcode::LdSPHL => {
482                self.advance_bus(bus);
483                self.reg_sp = self.reg_hl_read();
484                Ok(0)
485            }
486            Opcode::LdHLSPSigned8 => {
487                self.advance_bus(bus);
488                let result = self.reg_sp.wrapping_add(src);
489
490                self.flag_set(CpuFlags::Z, false);
491                self.flag_set(CpuFlags::N, false);
492                self.flag_set(CpuFlags::H, (self.reg_sp & 0xf) + (src & 0xf) > 0xf);
493                self.flag_set(CpuFlags::C, (self.reg_sp & 0xff) + (src & 0xff) > 0xff);
494
495                Ok(result)
496            }
497            Opcode::Push => {
498                self.advance_bus(bus);
499                self.stack_push(src, bus);
500                Ok(0)
501            }
502            Opcode::Pop => Ok(self.stack_pop(bus)),
503            Opcode::Inc16 => {
504                self.advance_bus(bus);
505                bus.trigger_write_oam_bug(src);
506                Ok(src.wrapping_add(1))
507            }
508
509            Opcode::Inc => {
510                let result = src.wrapping_add(1) & 0xff;
511
512                self.flag_set(CpuFlags::Z, result == 0);
513                self.flag_set(CpuFlags::N, false);
514                self.flag_set(CpuFlags::H, result & 0x0f == 0);
515
516                Ok(result)
517            }
518            Opcode::Dec16 => {
519                self.advance_bus(bus);
520                bus.trigger_write_oam_bug(src);
521                Ok(src.wrapping_sub(1))
522            }
523            Opcode::Dec => {
524                let result = src.wrapping_sub(1);
525                self.flag_set(CpuFlags::Z, result == 0);
526                self.flag_set(CpuFlags::N, true);
527                self.flag_set(CpuFlags::H, result & 0x0f == 0x0f);
528                Ok(result)
529            }
530            Opcode::Add => {
531                let dest = self.read_operand(instruction.dest, bus);
532                let result = dest.wrapping_add(src);
533
534                self.flag_set(CpuFlags::Z, result & 0xFF == 0);
535                self.flag_set(CpuFlags::N, false);
536                self.flag_set(CpuFlags::H, (dest & 0xf) + (src & 0xf) > 0xf);
537                self.flag_set(CpuFlags::C, result & 0xff00 != 0);
538
539                Ok(result & 0xFF)
540            }
541            Opcode::Add16 => {
542                self.advance_bus(bus);
543                let dest = self.read_operand(instruction.dest, bus);
544                let result = (dest as u32).wrapping_add(src as u32);
545
546                self.flag_set(CpuFlags::N, false);
547                self.flag_set(CpuFlags::H, (dest & 0xfff) + (src & 0xfff) > 0xfff);
548                self.flag_set(CpuFlags::C, result & 0xffff0000 != 0);
549
550                Ok(result as u16)
551            }
552            Opcode::AddSPSigned8 => {
553                self.advance_bus(bus);
554                self.advance_bus(bus);
555                let dest = self.read_operand(instruction.dest, bus);
556                let result = dest.wrapping_add(src);
557
558                self.flag_set(CpuFlags::Z, false);
559                self.flag_set(CpuFlags::N, false);
560                self.flag_set(CpuFlags::H, (dest & 0xf) + (src & 0xf) > 0xf);
561                self.flag_set(CpuFlags::C, (dest & 0xff) + (src & 0xff) > 0xff);
562
563                Ok(result)
564            }
565            Opcode::Adc => {
566                let dest = self.read_operand(instruction.dest, bus);
567                let carry = self.flag_get(CpuFlags::C) as u16;
568                let result = dest.wrapping_add(src).wrapping_add(carry);
569
570                self.flag_set(CpuFlags::Z, result & 0xFF == 0);
571                self.flag_set(CpuFlags::N, false);
572                self.flag_set(CpuFlags::H, (dest & 0xf) + (src & 0xf) + carry > 0xf);
573                self.flag_set(CpuFlags::C, result & 0xff00 != 0);
574
575                Ok(result)
576            }
577            Opcode::Sub => {
578                let dest = self.read_operand(instruction.dest, bus);
579                let result = dest.wrapping_sub(src);
580
581                self.flag_set(CpuFlags::Z, result & 0xFF == 0);
582                self.flag_set(CpuFlags::N, true);
583                self.flag_set(CpuFlags::H, (dest & 0xf) < (src & 0xf));
584                self.flag_set(CpuFlags::C, result & 0xff00 != 0);
585
586                Ok(result & 0xFF)
587            }
588            Opcode::Cp => {
589                let dest = self.reg_a as u16;
590                let result = dest.wrapping_sub(src);
591
592                self.flag_set(CpuFlags::Z, result & 0xFF == 0);
593                self.flag_set(CpuFlags::N, true);
594                self.flag_set(CpuFlags::H, (dest & 0xf) < (src & 0xf));
595                self.flag_set(CpuFlags::C, result & 0xff00 != 0);
596
597                // will be ignored
598                Ok(result & 0xFF)
599            }
600            Opcode::Sbc => {
601                let dest = self.read_operand(instruction.dest, bus);
602                let carry = self.flag_get(CpuFlags::C) as u16;
603                let result = dest.wrapping_sub(src).wrapping_sub(carry);
604
605                self.flag_set(CpuFlags::Z, result & 0xFF == 0);
606                self.flag_set(CpuFlags::N, true);
607                self.flag_set(
608                    CpuFlags::H,
609                    (dest & 0xf).wrapping_sub(src & 0xf).wrapping_sub(carry) > 0xf,
610                );
611                self.flag_set(CpuFlags::C, result & 0xff00 != 0);
612
613                Ok(result & 0xFF)
614            }
615            Opcode::And => {
616                let dest = self.read_operand(instruction.dest, bus);
617                let result = dest & src & 0xff;
618
619                self.flag_set(CpuFlags::Z, result == 0);
620                self.flag_set(CpuFlags::N, false);
621                self.flag_set(CpuFlags::H, true);
622                self.flag_set(CpuFlags::C, false);
623
624                Ok(result)
625            }
626            Opcode::Xor => {
627                let dest = self.read_operand(instruction.dest, bus);
628                let result = (dest ^ src) & 0xff;
629
630                self.flag_set(CpuFlags::Z, result == 0);
631                self.flag_set(CpuFlags::N, false);
632                self.flag_set(CpuFlags::H, false);
633                self.flag_set(CpuFlags::C, false);
634
635                Ok(result)
636            }
637            Opcode::Or => {
638                let dest = self.read_operand(instruction.dest, bus);
639                let result = (dest | src) & 0xff;
640
641                self.flag_set(CpuFlags::Z, result == 0);
642                self.flag_set(CpuFlags::N, false);
643                self.flag_set(CpuFlags::H, false);
644                self.flag_set(CpuFlags::C, false);
645
646                Ok(result)
647            }
648            Opcode::Jp(cond) => {
649                if self.check_cond(cond) {
650                    self.advance_bus(bus);
651                    if cond == Condition::Unconditional && src == instruction.pc {
652                        cpu_state = CpuState::InfiniteLoop;
653                    }
654
655                    self.reg_pc = src;
656                }
657                Ok(0)
658            }
659            Opcode::JpHL => {
660                if src == instruction.pc {
661                    cpu_state = CpuState::InfiniteLoop;
662                }
663
664                self.reg_pc = src;
665                Ok(0)
666            }
667            Opcode::Jr(cond) => {
668                if self.check_cond(cond) {
669                    self.advance_bus(bus);
670                    let new_pc = self.reg_pc.wrapping_add(src);
671
672                    if cond == Condition::Unconditional && new_pc == instruction.pc {
673                        cpu_state = CpuState::InfiniteLoop;
674                    }
675
676                    self.reg_pc = new_pc;
677                }
678                Ok(0)
679            }
680            Opcode::Call(cond) => {
681                if self.check_cond(cond) {
682                    self.advance_bus(bus);
683                    self.stack_push(self.reg_pc, bus);
684                    self.reg_pc = src;
685                }
686                Ok(0)
687            }
688            Opcode::Ret(cond) => {
689                if cond != Condition::Unconditional {
690                    self.advance_bus(bus);
691                }
692                if self.check_cond(cond) {
693                    self.reg_pc = self.stack_pop(bus);
694                    self.advance_bus(bus);
695                }
696                Ok(0)
697            }
698            Opcode::Reti => {
699                self.reg_pc = self.stack_pop(bus);
700                self.advance_bus(bus);
701                self.ime = true;
702                Ok(0)
703            }
704            Opcode::Rst(loc) => {
705                self.advance_bus(bus);
706                self.stack_push(self.reg_pc, bus);
707                self.reg_pc = loc as u16;
708                Ok(0)
709            }
710            Opcode::Di => {
711                self.ime = false;
712                Ok(0)
713            }
714            Opcode::Ei => {
715                self.enable_interrupt_next = true;
716                Ok(0)
717            }
718            Opcode::Ccf => {
719                self.flag_set(CpuFlags::N, false);
720                self.flag_set(CpuFlags::H, false);
721                self.flag_set(CpuFlags::C, !self.flag_get(CpuFlags::C));
722                Ok(0)
723            }
724            Opcode::Scf => {
725                self.flag_set(CpuFlags::N, false);
726                self.flag_set(CpuFlags::H, false);
727                self.flag_set(CpuFlags::C, true);
728                Ok(0)
729            }
730            Opcode::Daa => {
731                let carry = self.flag_get(CpuFlags::C);
732                let halfcarry = self.flag_get(CpuFlags::H);
733
734                if !self.flag_get(CpuFlags::N) {
735                    let mut correction = 0;
736                    if halfcarry || (self.reg_a & 0xf > 0x9) {
737                        correction |= 0x6;
738                    }
739
740                    if carry || (self.reg_a > 0x99) {
741                        correction |= 0x60;
742                        self.flag_set(CpuFlags::C, true);
743                    }
744
745                    self.reg_a = self.reg_a.wrapping_add(correction);
746                } else if carry {
747                    self.flag_set(CpuFlags::C, true);
748                    self.reg_a = self.reg_a.wrapping_add(if halfcarry { 0x9a } else { 0xa0 });
749                } else if halfcarry {
750                    self.reg_a = self.reg_a.wrapping_add(0xfa);
751                }
752
753                self.flag_set(CpuFlags::Z, self.reg_a == 0);
754                self.flag_set(CpuFlags::H, false);
755
756                Ok(0)
757            }
758            Opcode::Cpl => {
759                self.reg_a = !self.reg_a;
760
761                self.flag_set(CpuFlags::N, true);
762                self.flag_set(CpuFlags::H, true);
763
764                Ok(0)
765            }
766            Opcode::Rlca => {
767                let carry = (self.reg_a >> 7) & 1;
768                self.reg_a = self.reg_a.wrapping_shl(1) | carry;
769
770                self.flag_set(CpuFlags::Z, false);
771                self.flag_set(CpuFlags::N, false);
772                self.flag_set(CpuFlags::H, false);
773                self.flag_set(CpuFlags::C, carry == 1);
774
775                Ok(0)
776            }
777            Opcode::Rla => {
778                let carry = (self.reg_a >> 7) & 1;
779                self.reg_a = self.reg_a.wrapping_shl(1) | self.flag_get(CpuFlags::C) as u8;
780
781                self.flag_set(CpuFlags::Z, false);
782                self.flag_set(CpuFlags::N, false);
783                self.flag_set(CpuFlags::H, false);
784                self.flag_set(CpuFlags::C, carry == 1);
785
786                Ok(0)
787            }
788            Opcode::Rrca => {
789                let carry = self.reg_a & 1;
790                self.reg_a = self.reg_a.wrapping_shr(1) | (carry << 7);
791
792                self.flag_set(CpuFlags::Z, false);
793                self.flag_set(CpuFlags::N, false);
794                self.flag_set(CpuFlags::H, false);
795                self.flag_set(CpuFlags::C, carry == 1);
796
797                Ok(0)
798            }
799            Opcode::Rra => {
800                let carry = self.reg_a & 1;
801                self.reg_a = self.reg_a.wrapping_shr(1) | ((self.flag_get(CpuFlags::C) as u8) << 7);
802
803                self.flag_set(CpuFlags::Z, false);
804                self.flag_set(CpuFlags::N, false);
805                self.flag_set(CpuFlags::H, false);
806                self.flag_set(CpuFlags::C, carry == 1);
807
808                Ok(0)
809            }
810            Opcode::Rlc => {
811                let carry = (src >> 7) & 1;
812                let result = src.wrapping_shl(1) | carry & 0xFF;
813
814                self.flag_set(CpuFlags::Z, result == 0);
815                self.flag_set(CpuFlags::N, false);
816                self.flag_set(CpuFlags::H, false);
817                self.flag_set(CpuFlags::C, carry == 1);
818
819                Ok(result)
820            }
821            Opcode::Rrc => {
822                let carry = src & 1;
823                let result = src.wrapping_shr(1) | (carry << 7) & 0xFF;
824
825                self.flag_set(CpuFlags::Z, result == 0);
826                self.flag_set(CpuFlags::N, false);
827                self.flag_set(CpuFlags::H, false);
828                self.flag_set(CpuFlags::C, carry == 1);
829
830                Ok(result)
831            }
832            Opcode::Rl => {
833                let carry = (src >> 7) & 1;
834                let result = (src.wrapping_shl(1) | self.flag_get(CpuFlags::C) as u16) & 0xFF;
835
836                self.flag_set(CpuFlags::Z, result == 0);
837                self.flag_set(CpuFlags::N, false);
838                self.flag_set(CpuFlags::H, false);
839                self.flag_set(CpuFlags::C, carry == 1);
840
841                Ok(result)
842            }
843            Opcode::Rr => {
844                let carry = src & 1;
845                let result =
846                    (src.wrapping_shr(1) | ((self.flag_get(CpuFlags::C) as u16) << 7)) & 0xFF;
847
848                self.flag_set(CpuFlags::Z, result == 0);
849                self.flag_set(CpuFlags::N, false);
850                self.flag_set(CpuFlags::H, false);
851                self.flag_set(CpuFlags::C, carry == 1);
852
853                Ok(result)
854            }
855            Opcode::Sla => {
856                let carry = (src >> 7) & 1;
857                let result = src.wrapping_shl(1) & 0xFF;
858
859                self.flag_set(CpuFlags::Z, result == 0);
860                self.flag_set(CpuFlags::N, false);
861                self.flag_set(CpuFlags::H, false);
862                self.flag_set(CpuFlags::C, carry == 1);
863
864                Ok(result)
865            }
866            Opcode::Sra => {
867                let carry = src & 1;
868                let result = (src.wrapping_shr(1) | (src & 0x80)) & 0xFF;
869
870                self.flag_set(CpuFlags::Z, result == 0);
871                self.flag_set(CpuFlags::N, false);
872                self.flag_set(CpuFlags::H, false);
873                self.flag_set(CpuFlags::C, carry == 1);
874
875                Ok(result)
876            }
877            Opcode::Swap => {
878                let result = ((src >> 4) & 0xf) | ((src & 0xf) << 4);
879
880                self.flag_set(CpuFlags::Z, result == 0);
881                self.flag_set(CpuFlags::N, false);
882                self.flag_set(CpuFlags::H, false);
883                self.flag_set(CpuFlags::C, false);
884
885                Ok(result)
886            }
887            Opcode::Srl => {
888                let carry = src & 1;
889                let result = src.wrapping_shr(1) & 0xFF;
890
891                self.flag_set(CpuFlags::Z, result == 0);
892                self.flag_set(CpuFlags::N, false);
893                self.flag_set(CpuFlags::H, false);
894                self.flag_set(CpuFlags::C, carry == 1);
895
896                Ok(result)
897            }
898            Opcode::Bit(bit) => {
899                self.flag_set(CpuFlags::Z, (src >> bit) & 1 == 0);
900                self.flag_set(CpuFlags::N, false);
901                self.flag_set(CpuFlags::H, true);
902                Ok(0)
903            }
904            Opcode::Res(bit) => Ok(src & !((1 << bit) as u16)),
905            Opcode::Set(bit) => Ok(src | ((1 << bit) as u16)),
906            Opcode::Halt => {
907                // When halt instruction is executed several outcomes might occur:
908                // - When IME = 1:
909                //      In this case, the halt instruction works normally. It will
910                //      stop exection and wait until an interrupt occure (`IF & IE & 0x1F != 0`),
911                //      then it will exit halt mode and execute the interrupt normally.
912                // - When IME = 0:
913                //      - If an interrupt is waiting (`IF & IE & 0x1F != 0`), it
914                //        will enter a `Halt bug` state, in this state, the halt
915                //        mode is not entered and the PC register is not incremented
916                //        on the next instruction.
917                //      - If an interrupt is not waiting (`IF & IE & 0x1F == 0`),
918                //        the cpu will enter halt mode normally and wait for an interrupt
919                //        to occur like in *IME = 1* case but if an interrupt is
920                //        requested it will not just to the interrupt vector
921                //        and it will continue executing normally, we can think
922                //        of it as being stuck in a large array of NOP instructions
923                //        until an interrupt is requested.
924                self.halt_mode = if self.ime {
925                    HaltMode::HaltRunInterrupt
926                } else if bus.peek_next_interrupt().is_some() {
927                    HaltMode::HaltBug
928                } else {
929                    HaltMode::HaltNoRunInterrupt
930                };
931
932                Ok(0)
933            }
934            Opcode::Stop => {
935                // TODO: respect wait time for speed switch
936                bus.enter_stop_mode();
937                Ok(0)
938            }
939            Opcode::Illegal => Err(RunError::IllegalInstruction),
940            Opcode::Prefix => unreachable!(),
941        }?;
942
943        // DEBUG
944        // println!(
945        //     "{:04X}: {}, src={:04X}, result={:04X}",
946        //     instruction.pc, instruction, src, result
947        // );
948
949        self.write_operand(instruction.dest, result, bus);
950
951        Ok(cpu_state)
952    }
953}