io.rsannotatedio.rssource106 lines · 3.5 KB · raw
1use crate::core::instructions::{
2    BlockMode, InstructionExecutor, parity_flag, sign_flag, zero_flag,
3};
4use crate::core::{Flags, Register16};
5use crate::debug::BusDebugExt;
6use crate::traits::BusInterface;
7
8impl<B: BusInterface> InstructionExecutor<'_, '_, B> {
9    pub(super) fn in_a_n(&mut self) -> u32 {
10        let operand = self.fetch_operand();
11        let io_address = u16::from_be_bytes([self.cpu.registers.a, operand]);
12
13        self.cpu.registers.a = self.bus.read_io_debug(io_address, self.cpu);
14
15        11
16    }
17
18    pub(super) fn in_r_c(&mut self, opcode: u8) -> u32 {
19        let register = super::parse_register_from_opcode(opcode >> 3, None);
20        let io_address = u16::from_be_bytes([self.cpu.registers.b, self.cpu.registers.c]);
21        let value = self.bus.read_io_debug(io_address, self.cpu);
22
23        if let Some(register) = register {
24            register.write_to(value, &mut self.cpu.registers);
25        }
26
27        self.cpu.registers.f = Flags {
28            sign: sign_flag(value),
29            zero: zero_flag(value),
30            half_carry: false,
31            overflow: parity_flag(value),
32            subtract: false,
33            ..self.cpu.registers.f
34        };
35
36        12
37    }
38
39    pub(super) fn in_block(&mut self, mode: BlockMode, repeat: bool) -> u32 {
40        let b = self.cpu.registers.b;
41        let io_address = u16::from_be_bytes([b, self.cpu.registers.c]);
42        let value = self.bus.read_io_debug(io_address, self.cpu);
43
44        let hl = Register16::HL.read_from(&self.cpu.registers);
45        self.bus.write_memory_debug(hl, value, self.cpu);
46
47        self.cpu.registers.b = b.wrapping_sub(1);
48
49        Register16::HL.write_to(mode.apply(hl), &mut self.cpu.registers);
50
51        let should_repeat = repeat && b != 1;
52        if should_repeat {
53            self.cpu.registers.pc -= 2;
54        }
55
56        self.cpu.registers.f =
57            Flags { zero: repeat || b == 1, subtract: true, ..self.cpu.registers.f };
58
59        if should_repeat { 21 } else { 16 }
60    }
61
62    pub(super) fn out_n_a(&mut self) -> u32 {
63        let operand = self.fetch_operand();
64        let io_address = u16::from_be_bytes([self.cpu.registers.a, operand]);
65
66        self.bus.write_io_debug(io_address, self.cpu.registers.a, self.cpu);
67
68        11
69    }
70
71    pub(super) fn out_c_r(&mut self, opcode: u8) -> u32 {
72        let register = super::parse_register_from_opcode(opcode >> 3, None);
73        let io_address = u16::from_be_bytes([self.cpu.registers.b, self.cpu.registers.c]);
74        let value = match register {
75            Some(register) => register.read_from(&self.cpu.registers),
76            None => 0,
77        };
78
79        self.bus.write_io_debug(io_address, value, self.cpu);
80
81        12
82    }
83
84    pub(super) fn out_block(&mut self, mode: BlockMode, repeat: bool) -> u32 {
85        let hl = Register16::HL.read_from(&self.cpu.registers);
86        let value = self.bus.read_memory_debug(hl, self.cpu);
87
88        let b = self.cpu.registers.b;
89        self.cpu.registers.b = b.wrapping_sub(1);
90
91        let io_address = u16::from_be_bytes([self.cpu.registers.b, self.cpu.registers.c]);
92        self.bus.write_io_debug(io_address, value, self.cpu);
93
94        Register16::HL.write_to(mode.apply(hl), &mut self.cpu.registers);
95
96        let should_repeat = repeat && b != 1;
97        if should_repeat {
98            self.cpu.registers.pc -= 2;
99        }
100
101        self.cpu.registers.f =
102            Flags { zero: repeat || b == 1, subtract: true, ..self.cpu.registers.f };
103
104        if should_repeat { 21 } else { 16 }
105    }
106}