ruboy_lib/cpu/
mod.rs

1mod nums;
2mod registers;
3mod timer;
4
5use core::num::Wrapping;
6
7use nums::{GbBits, GbHalfCarry};
8use thiserror::Error;
9
10use registers::Registers;
11
12use crate::{
13    extern_traits::{GBAllocator, RomReader},
14    isa::*,
15    memcontroller::{
16        interrupts::Interrupts, MemController, MemControllerDecoderErr, ReadError, WriteError,
17    },
18};
19
20pub struct Cpu {
21    timer_cycles: Wrapping<usize>,
22    cycles_remaining: u8,
23    interrupts_master: bool,
24    /// Whether the interrupts master flag should be re-enabled after the next instruction
25    ei_queued: bool,
26
27    registers: Registers,
28}
29
30#[derive(Debug, Error)]
31pub enum CpuErr {
32    #[error("Error during instruction decoding")]
33    Decode(#[from] MemControllerDecoderErr),
34
35    #[error("Illegal instruction: 0x{:x}", 0)]
36    Illegal(u8),
37
38    #[error("Could not write to memory")]
39    MemWriteError(#[from] WriteError),
40
41    #[error("Could not read from memory")]
42    MemReadError(#[from] ReadError),
43}
44
45macro_rules! instr_todo {
46    ($instr:expr) => {
47        todo!("{}", $instr)
48    };
49}
50
51impl Cpu {
52    pub fn new() -> Self {
53        Cpu {
54            timer_cycles: Wrapping(0),
55            cycles_remaining: 0,
56            interrupts_master: false,
57            ei_queued: false,
58            registers: Registers::new(),
59        }
60    }
61
62    #[inline]
63    const fn get_reg16_value(&self, reg: Reg16) -> u16 {
64        match reg {
65            Reg16::AF => self.registers.af(),
66            Reg16::BC => self.registers.bc(),
67            Reg16::DE => self.registers.de(),
68            Reg16::HL => self.registers.hl(),
69            Reg16::SP => self.registers.sp(),
70        }
71    }
72
73    #[inline]
74    const fn get_reg8_value(&self, reg: Reg8) -> u8 {
75        match reg {
76            Reg8::A => self.registers.a(),
77            Reg8::B => self.registers.b(),
78            Reg8::C => self.registers.c(),
79            Reg8::D => self.registers.d(),
80            Reg8::E => self.registers.e(),
81            Reg8::F => self.registers.f(),
82            Reg8::H => self.registers.h(),
83            Reg8::L => self.registers.l(),
84        }
85    }
86
87    #[inline]
88    fn set_reg8_value(&mut self, reg: Reg8, val: u8) {
89        match reg {
90            Reg8::A => self.registers.set_a(val),
91            Reg8::B => self.registers.set_b(val),
92            Reg8::C => self.registers.set_c(val),
93            Reg8::D => self.registers.set_d(val),
94            Reg8::E => self.registers.set_e(val),
95            Reg8::F => self.registers.set_f(val),
96            Reg8::H => self.registers.set_h(val),
97            Reg8::L => self.registers.set_l(val),
98        }
99    }
100
101    #[inline]
102    fn set_reg16_value(&mut self, reg: Reg16, val: u16) {
103        match reg {
104            Reg16::AF => self.registers.set_af(val),
105            Reg16::BC => self.registers.set_bc(val),
106            Reg16::DE => self.registers.set_de(val),
107            Reg16::HL => self.registers.set_hl(val),
108            Reg16::SP => self.registers.set_sp(val),
109        }
110    }
111
112    fn memloc_to_addr(&self, memloc: MemLoc) -> u16 {
113        match memloc {
114            MemLoc::HighMemReg(reg) => 0xFF00 | (self.get_reg8_value(reg) as u16),
115            MemLoc::Reg(reg) => self.get_reg16_value(reg),
116            MemLoc::HighMemImm(imm) => 0xFF00 | (imm as u16),
117            MemLoc::Imm(imm) => imm,
118        }
119    }
120
121    fn check_condition(&self, cond: Condition) -> bool {
122        match cond {
123            Condition::Zero => self.registers.zero_flag(),
124            Condition::NotZero => !self.registers.zero_flag(),
125            Condition::Carry => self.registers.carry_flag(),
126            Condition::NotCarry => !self.registers.carry_flag(),
127        }
128    }
129
130    fn do_rel_jump(&mut self, base: u16, offset: i8) {
131        let jump_addr = u16::try_from((base as i32) + (offset as i32)).unwrap();
132        self.registers.set_pc(jump_addr);
133    }
134
135    fn do_push8(
136        &mut self,
137        mem: &mut MemController<impl GBAllocator, impl RomReader>,
138        val: u8,
139    ) -> Result<(), WriteError> {
140        self.registers.set_sp(self.registers.sp() - 1);
141        mem.write8(self.registers.sp(), val)
142    }
143
144    fn do_pop8(
145        &mut self,
146        mem: &mut MemController<impl GBAllocator, impl RomReader>,
147    ) -> Result<u8, ReadError> {
148        let val = mem.read8(self.registers.sp());
149
150        self.registers.set_sp(self.registers.sp() + 1);
151
152        val
153    }
154
155    fn do_push16(
156        &mut self,
157        mem: &mut MemController<impl GBAllocator, impl RomReader>,
158        val: u16,
159    ) -> Result<(), WriteError> {
160        self.registers.set_sp(self.registers.sp() - 2);
161        mem.write16(self.registers.sp(), val)
162    }
163
164    fn do_pop16(
165        &mut self,
166        mem: &mut MemController<impl GBAllocator, impl RomReader>,
167    ) -> Result<u16, ReadError> {
168        let val = mem.read16(self.registers.sp());
169
170        self.registers.set_sp(self.registers.sp() + 2);
171
172        val
173    }
174
175    fn do_call(
176        &mut self,
177        mem: &mut MemController<impl GBAllocator, impl RomReader>,
178        return_addr: u16,
179        call_addr: u16,
180    ) -> Result<(), WriteError> {
181        self.do_push16(mem, return_addr)?;
182        self.registers.set_pc(call_addr);
183        Ok(())
184    }
185
186    fn get_arith_src(
187        &self,
188        mem: &MemController<impl GBAllocator, impl RomReader>,
189        src: ArithSrc,
190    ) -> Result<u8, ReadError> {
191        match src {
192            ArithSrc::Reg(reg) => Ok(self.get_reg8_value(reg)),
193            ArithSrc::Imm(imm) => Ok(imm),
194            ArithSrc::Mem(memloc) => mem.read8(self.memloc_to_addr(memloc)),
195        }
196    }
197
198    fn get_prefarith_tgt(
199        &self,
200        mem: &MemController<impl GBAllocator, impl RomReader>,
201        tgt: PrefArithTarget,
202    ) -> Result<u8, ReadError> {
203        match tgt {
204            PrefArithTarget::Reg(reg) => Ok(self.get_reg8_value(reg)),
205            PrefArithTarget::MemHL => mem.read8(self.registers.hl()),
206        }
207    }
208
209    fn set_prefarith_tgt(
210        &mut self,
211        mem: &mut MemController<impl GBAllocator, impl RomReader>,
212        tgt: PrefArithTarget,
213        val: u8,
214    ) -> Result<(), WriteError> {
215        match tgt {
216            PrefArithTarget::Reg(reg) => {
217                self.set_reg8_value(reg, val);
218                Ok(())
219            }
220            PrefArithTarget::MemHL => mem.write8(self.registers.hl(), val),
221        }
222    }
223
224    fn handle_timers(&mut self, mem: &mut MemController<impl GBAllocator, impl RomReader>) {
225        if self.timer_cycles.0 % 256 == 0 {
226            mem.io_registers.timer_div += 1;
227        }
228
229        if let Some(tac_frequency) = timer::get_tac_modulo(mem.io_registers.timer_control) {
230            if self.timer_cycles.0 % tac_frequency == 0 {
231                let (incremented, overflown) = mem.io_registers.timer_counter.overflowing_add(1);
232
233                if overflown {
234                    mem.io_registers.timer_counter = mem.io_registers.timer_modulo;
235                    mem.io_registers.interrupts_requested.set_timer(true);
236                } else {
237                    mem.io_registers.timer_counter = incremented;
238                }
239            }
240        }
241
242        self.timer_cycles += 1;
243    }
244
245    pub fn run_cycle(
246        &mut self,
247        mem: &mut MemController<impl GBAllocator, impl RomReader>,
248    ) -> Result<(), CpuErr> {
249        self.handle_timers(mem);
250
251        if self.cycles_remaining != 0 {
252            // Still executing, continue later
253            self.cycles_remaining -= 1;
254            return Ok(());
255        }
256
257        let instr = decoder::decode(mem, self.registers.pc())?;
258
259        log::trace!("Running 0x{:x}: {}", self.registers.pc(), instr);
260
261        let should_enable_interrupts = self.ei_queued;
262
263        let jumped = match instr {
264            Instruction::Nop => false,
265            Instruction::Stop(_) => instr_todo!(instr),
266            Instruction::Halt => instr_todo!(instr),
267            Instruction::EI => {
268                self.ei_queued = true;
269                false
270            }
271            Instruction::DI => {
272                self.interrupts_master = false;
273                false
274            }
275            Instruction::Add(src) => {
276                let base = self.registers.a();
277                let val = self.get_arith_src(mem, src)?;
278
279                let (res, carry) = base.overflowing_add(val);
280
281                self.registers
282                    .set_flags(res == 0, false, base.halfcarry_add(val), carry);
283
284                self.registers.set_a(res);
285
286                false
287            }
288            Instruction::AddCarry(src) => {
289                let base = self.registers.a();
290                let val = self.get_arith_src(mem, src)?;
291                let cur_carry = if self.registers.carry_flag() { 1 } else { 0 };
292
293                let (res, new_carry) = base.overflowing_add(val + cur_carry);
294
295                self.registers.set_flags(
296                    res == 0,
297                    false,
298                    base.halfcarry_add(val + cur_carry),
299                    new_carry,
300                );
301
302                self.registers.set_a(res);
303
304                false
305            }
306            Instruction::AddHL(reg) => {
307                let base = self.registers.hl();
308                let val = self.get_reg16_value(reg);
309
310                let (res, carry) = base.overflowing_add(val);
311
312                self.registers
313                    .set_flags(res == 0, false, base.halfcarry_add(val), carry);
314
315                self.registers.set_hl(res);
316
317                false
318            }
319            Instruction::AddSP(_) => instr_todo!(instr),
320            Instruction::Sub(src) => {
321                let base = self.registers.a();
322                let val = self.get_arith_src(mem, src)?;
323
324                let (res, carry) = base.overflowing_sub(val);
325
326                self.registers
327                    .set_flags(res == 0, true, base.halfcarry_sub(val), carry);
328
329                self.registers.set_a(res);
330
331                false
332            }
333            Instruction::SubCarry(_) => instr_todo!(instr),
334            Instruction::And(src) => {
335                let val = self.get_arith_src(mem, src)?;
336
337                let and = val & self.registers.a();
338
339                self.registers.set_flags(and == 0, false, true, false);
340                self.registers.set_a(and);
341
342                false
343            }
344            Instruction::Or(src) => {
345                let val = self.get_arith_src(mem, src)?;
346
347                let or = val | self.registers.a();
348
349                self.registers.set_flags(or == 0, false, false, false);
350                self.registers.set_a(or);
351
352                false
353            }
354            Instruction::Xor(src) => {
355                let val = self.get_arith_src(mem, src)?;
356
357                let xord = self.registers.a() ^ val;
358
359                self.registers.set_a(xord);
360
361                self.registers.set_flags(xord == 0, false, false, false);
362
363                false
364            }
365            Instruction::Cmp(src) => {
366                let base = self.registers.a();
367                let val = self.get_arith_src(mem, src)?;
368
369                let (res, carry) = base.overflowing_sub(val);
370
371                self.registers
372                    .set_flags(res == 0, true, base.halfcarry_sub(val), carry);
373
374                false
375            }
376            Instruction::Inc(tgt) => {
377                match tgt {
378                    IncDecTarget::Reg8(reg) => {
379                        let val = self.get_reg8_value(reg);
380                        let incremented = val.wrapping_add(1);
381
382                        self.registers.set_zero_flag(incremented == 0);
383                        self.registers.set_subtract_flag(false);
384                        self.registers.set_half_carry_flag(val.halfcarry_add(1));
385
386                        self.set_reg8_value(reg, incremented);
387                    }
388                    IncDecTarget::Reg16(reg) => {
389                        let val = self.get_reg16_value(reg);
390                        let incremented = val.wrapping_add(1);
391
392                        self.set_reg16_value(reg, incremented);
393                    }
394                    IncDecTarget::MemHL => {
395                        let addr = self.registers.hl();
396                        let val = mem.read8(addr)?;
397                        let incremented = val.wrapping_add(1);
398
399                        self.registers.set_zero_flag(incremented == 0);
400                        self.registers.set_subtract_flag(false);
401                        self.registers.set_half_carry_flag(val.halfcarry_add(1));
402
403                        mem.write8(addr, incremented)?;
404                    }
405                };
406                false
407            }
408            Instruction::Dec(tgt) => {
409                match tgt {
410                    IncDecTarget::Reg8(reg) => {
411                        let val = self.get_reg8_value(reg);
412                        let decremented = val.wrapping_sub(1);
413
414                        self.registers.set_zero_flag(decremented == 0);
415                        self.registers.set_subtract_flag(true);
416                        self.registers.set_half_carry_flag(val.halfcarry_sub(1));
417
418                        self.set_reg8_value(reg, decremented);
419                    }
420                    IncDecTarget::Reg16(reg) => {
421                        let val = self.get_reg16_value(reg);
422                        let decremented = val.wrapping_sub(1);
423
424                        self.set_reg16_value(reg, decremented);
425                    }
426                    IncDecTarget::MemHL => {
427                        let addr = self.registers.hl();
428                        let val = mem.read8(addr)?;
429                        let decremented = val.wrapping_sub(1);
430
431                        self.registers.set_zero_flag(decremented == 0);
432                        self.registers.set_subtract_flag(true);
433                        self.registers.set_half_carry_flag(val.halfcarry_sub(1));
434
435                        mem.write8(addr, decremented)?;
436                    }
437                };
438                false
439            }
440            Instruction::RotLeftCircular(_) => instr_todo!(instr),
441            Instruction::RotRightCircular(tgt) => {
442                let pre = self.get_prefarith_tgt(mem, tgt)?;
443
444                self.registers.set_carry_flag(pre.lsb_set());
445
446                self.set_prefarith_tgt(mem, tgt, pre.rotate_right(1))?;
447
448                false
449            }
450            Instruction::RotLeft(tgt) => {
451                let init_val = self.get_prefarith_tgt(mem, tgt)?;
452                let shifted = init_val.wrapping_shl(1);
453                let result = shifted.set_lsb(self.registers.carry_flag());
454
455                self.registers
456                    .set_flags(result == 0, false, false, init_val.msb_set());
457
458                self.set_prefarith_tgt(mem, tgt, result)?;
459
460                false
461            }
462            Instruction::RotRight(_) => instr_todo!(instr),
463            Instruction::ShiftLeftArith(tgt) => {
464                let init_val = self.get_prefarith_tgt(mem, tgt)?;
465                let shifted = init_val.wrapping_shl(1);
466
467                self.registers
468                    .set_flags(shifted == 0, false, false, init_val.msb_set());
469
470                self.set_prefarith_tgt(mem, tgt, shifted)?;
471
472                false
473            }
474            Instruction::ShiftRightArith(_) => instr_todo!(instr),
475            Instruction::Swap(tgt) => {
476                let val = self.get_prefarith_tgt(mem, tgt)?;
477                let val_lower = val & 0xF;
478                let val_upper = val & 0xF0;
479
480                let swapped = (val_lower << 4) | (val_upper >> 4);
481
482                self.set_prefarith_tgt(mem, tgt, swapped)?;
483
484                self.registers.set_flags(swapped == 0, false, false, false);
485
486                false
487            }
488            Instruction::ShiftRightLogic(tgt) => {
489                let val = self.get_prefarith_tgt(mem, tgt)?;
490
491                let carry = val.lsb_set();
492
493                let res = val.wrapping_shr(1);
494
495                self.registers.set_flags(res == 0, false, false, carry);
496
497                self.set_prefarith_tgt(mem, tgt, res)?;
498
499                false
500            }
501            Instruction::Bit(bit, tgt) => {
502                let val = self.get_prefarith_tgt(mem, tgt)?;
503
504                let is_zero = val & (1 << (bit as usize)) == 0;
505
506                self.registers.set_zero_flag(is_zero);
507                self.registers.set_subtract_flag(false);
508                self.registers.set_half_carry_flag(true);
509
510                false
511            }
512            Instruction::Res(bit, tgt) => {
513                let val = self.get_prefarith_tgt(mem, tgt)?;
514
515                let bit: u8 = 0b1 << bit as usize;
516
517                self.set_prefarith_tgt(mem, tgt, val & (!bit))?;
518
519                false
520            }
521            Instruction::Set(bit, tgt) => {
522                let val = self.get_prefarith_tgt(mem, tgt)?;
523
524                let bit: u8 = 0b1 << bit as usize;
525
526                self.set_prefarith_tgt(mem, tgt, val | bit)?;
527
528                false
529            }
530            Instruction::Load8(dst, src) => {
531                let val = match src {
532                    Ld8Src::Reg(reg) => self.get_reg8_value(reg),
533                    Ld8Src::Mem(memloc) => mem.read8(self.memloc_to_addr(memloc))?,
534                    Ld8Src::Imm(imm) => imm,
535                };
536
537                match dst {
538                    Ld8Dst::Mem(memloc) => mem.write8(self.memloc_to_addr(memloc), val)?,
539                    Ld8Dst::Reg(reg) => self.set_reg8_value(reg, val),
540                };
541
542                false
543            }
544            Instruction::Load16(dst, src) => {
545                let val = match src {
546                    Ld16Src::Reg(reg) => self.get_reg16_value(reg),
547                    Ld16Src::Imm(imm) => imm,
548                };
549
550                match dst {
551                    Ld16Dst::Mem(memloc) => mem.write16(self.memloc_to_addr(memloc), val)?,
552                    Ld16Dst::Reg(reg) => self.set_reg16_value(reg, val),
553                };
554
555                false
556            }
557            Instruction::LoadAtoHLI => {
558                let val = self.registers.a();
559                let addr = self.registers.hl();
560
561                mem.write8(addr, val)?;
562
563                self.registers.set_hl(addr + 1);
564
565                false
566            }
567            Instruction::LoadAtoHLD => {
568                let val = self.registers.a();
569                let addr = self.registers.hl();
570
571                mem.write8(addr, val)?;
572
573                self.registers.set_hl(addr - 1);
574
575                false
576            }
577            Instruction::LoadHLItoA => {
578                let addr = self.registers.hl();
579                let val = mem.read8(addr)?;
580
581                self.registers.set_hl(addr + 1); // This increments HL
582                self.registers.set_a(val);
583
584                false
585            }
586            Instruction::LoadHLDtoA => {
587                let addr = self.registers.hl();
588                let val = mem.read8(addr)?;
589
590                self.registers.set_hl(addr - 1); // This decrements HL
591                self.registers.set_a(val);
592
593                false
594            }
595            Instruction::LoadSPi8toHL(_) => instr_todo!(instr),
596            Instruction::Jump(addr) => {
597                self.registers.set_pc(addr);
598                true
599            }
600            Instruction::JumpRel(offset) => {
601                self.do_rel_jump(self.registers.pc() + (instr.len() as u16), offset);
602                true
603            }
604            Instruction::JumpHL => {
605                self.registers.set_pc(self.registers.hl());
606                true
607            }
608            Instruction::JumpIf(addr, cond) => {
609                if self.check_condition(cond) {
610                    self.registers.set_pc(addr);
611                    true
612                } else {
613                    false
614                }
615            }
616            Instruction::JumpRelIf(offset, condition) => {
617                if self.check_condition(condition) {
618                    self.do_rel_jump(self.registers.pc() + (instr.len() as u16), offset);
619                    true
620                } else {
621                    false
622                }
623            }
624            Instruction::Call(addr) => {
625                let curr_addr = self.registers.pc();
626                let return_addr = curr_addr + (instr.len() as u16);
627
628                self.do_call(mem, return_addr, addr)?;
629
630                true
631            }
632            Instruction::CallIf(addr, cond) => {
633                if self.check_condition(cond) {
634                    let curr_addr = self.registers.pc();
635                    let return_addr = curr_addr + (instr.len() as u16);
636
637                    self.do_call(mem, return_addr, addr)?;
638
639                    true
640                } else {
641                    false
642                }
643            }
644            Instruction::Ret => {
645                let ret_addr = self.do_pop16(mem)?;
646                self.registers.set_pc(ret_addr);
647
648                true
649            }
650            Instruction::Reti => {
651                // TODO: Not entirely sure if the order and timings
652                // of enabling/disabling interrupts is correct.
653                let ret_addr = self.do_pop16(mem)?;
654                self.registers.set_pc(ret_addr);
655                self.interrupts_master = true; // This is definitely not correct
656
657                true
658            }
659            Instruction::RetIf(cond) => {
660                if self.check_condition(cond) {
661                    let ret_addr = self.do_pop16(mem)?;
662                    self.registers.set_pc(ret_addr);
663
664                    true
665                } else {
666                    false
667                }
668            }
669            Instruction::Pop(reg) => {
670                let val = self.do_pop16(mem)?;
671                self.set_reg16_value(reg, val);
672
673                false
674            }
675            Instruction::Push(reg) => {
676                self.do_push16(mem, self.get_reg16_value(reg))?;
677
678                false
679            }
680            Instruction::DecimalAdjust => {
681                let mut a = self.registers.a();
682                let cflag = self.registers.carry_flag();
683                let hflag = self.registers.half_carry_flag();
684
685                match self.registers.subtract_flag() {
686                    false => {
687                        if cflag || a > 0x99 {
688                            a = a.wrapping_add(0x60);
689                            self.registers.set_carry_flag(true);
690                        }
691                        if hflag || (a & 0x0F) > 0x09 {
692                            a = a.wrapping_add(0x6);
693                        }
694                    }
695                    true => {
696                        if cflag {
697                            a = a.wrapping_sub(0x60);
698                        }
699                        if hflag {
700                            a = a.wrapping_sub(0x6);
701                        }
702                    }
703                }
704
705                self.registers.set_zero_flag(a == 0);
706                self.registers.set_half_carry_flag(false);
707                self.registers.set_a(a);
708
709                false
710            }
711            Instruction::ComplementAccumulator => {
712                self.registers.set_a(!self.registers.a());
713                self.registers.set_subtract_flag(true);
714                self.registers.set_half_carry_flag(true);
715                false
716            }
717            Instruction::SetCarryFlag => instr_todo!(instr),
718            Instruction::ComplementCarry => instr_todo!(instr),
719            Instruction::Rst(rsvec) => {
720                let curr_addr = self.registers.pc();
721                let return_addr = curr_addr + (instr.len() as u16);
722
723                self.do_call(mem, return_addr, rsvec as u16)?;
724
725                true
726            }
727            Instruction::RotLeftCircularA => {
728                let pre = self.registers.a();
729
730                self.registers.set_carry_flag(pre.msb_set());
731
732                self.registers.set_a(pre.rotate_left(1));
733
734                false
735            }
736            Instruction::RotRightCircularA => {
737                let pre = self.registers.a();
738
739                self.registers.set_carry_flag(pre.lsb_set());
740
741                self.registers.set_a(pre.rotate_right(1));
742
743                false
744            }
745            Instruction::RotLeftA => {
746                let cur_val = self.registers.a();
747                let shifted = cur_val.wrapping_shl(1);
748                let result = shifted.set_lsb(self.registers.carry_flag());
749
750                self.registers
751                    .set_flags(false, false, false, cur_val.msb_set());
752
753                self.registers.set_a(result);
754
755                false
756            }
757            Instruction::RotRightA => instr_todo!(instr),
758            Instruction::IllegalInstruction(illegal) => {
759                return Err(CpuErr::Illegal(illegal));
760            }
761        };
762
763        if should_enable_interrupts {
764            self.ei_queued = false;
765            self.interrupts_master = true;
766        }
767
768        // Set PC to next instruction, if we didn't jump
769        if !jumped {
770            let instr_len = instr.len() as u16;
771
772            self.registers.set_pc(self.registers.pc() + instr_len);
773        }
774
775        // Handle any interrupts.
776        if self.interrupts_master {
777            let enabled = mem.interrupts_enabled;
778            let requested = mem.io_registers.interrupts_requested;
779            let to_service: Interrupts = (u8::from(enabled) & u8::from(requested)).into();
780
781            // We have an interrupt! Disable any following interrupts
782            // and go to the handler. We check for zero
783            // with the lower 5 bits, because the upper 3 are unused
784            // and thus do not actually correspond to an interrupt
785            if u8::from(to_service) & 0b00011111 != 0 {
786                log::debug!("Handling interrupt! 0b{:b}", u8::from(to_service));
787                self.interrupts_master = false;
788
789                let handler_addr: u16 = if to_service.vblank() {
790                    mem.io_registers.interrupts_requested.set_vblank(false);
791                    0x40
792                } else if to_service.lcd() {
793                    mem.io_registers.interrupts_requested.set_lcd(false);
794                    0x48
795                } else if to_service.timer() {
796                    mem.io_registers.interrupts_requested.set_timer(false);
797                    0x50
798                } else if to_service.serial() {
799                    mem.io_registers.interrupts_requested.set_serial(false);
800                    0x58
801                } else if to_service.joypad() {
802                    mem.io_registers.interrupts_requested.set_joypad(false);
803                    0x60
804                } else {
805                    unreachable!("Not actually an interrupt");
806                };
807
808                // Return addr is just the current PC now, since we were interrupted before executing it
809                self.do_call(mem, self.registers.pc(), handler_addr)?;
810                self.cycles_remaining = 20; // Entire interrupt routine takes 20 cycles to complete
811                return Ok(());
812            }
813        }
814
815        // No interrupt was handled. Just continue execution as usual
816        match instr.cycles() {
817            TCycles::Static(cycles) => self.cycles_remaining = cycles - 1,
818            TCycles::Branching { taken, non_taken } => {
819                let actual_cycles = if jumped { taken } else { non_taken };
820
821                self.cycles_remaining = actual_cycles - 1;
822            }
823        }
824
825        Ok(())
826    }
827}