1use crate::{
4 opcode::{
5 execute_bits, execute_extended, execute_normal, execute_pop_16, execute_push_16, Opcode,
6 Prefix,
7 },
8 RegName16, Regs, Z80Bus,
9};
10
11#[derive(Debug, Clone, Copy)]
13pub enum IntMode {
14 Im0,
15 Im1,
16 Im2,
17}
18
19impl From<IntMode> for u8 {
20 fn from(mode: IntMode) -> Self {
21 match mode {
22 IntMode::Im0 => 0,
23 IntMode::Im1 => 1,
24 IntMode::Im2 => 2,
25 }
26 }
27}
28
29pub struct Z80 {
31 pub regs: Regs,
33 pub(crate) halted: bool,
35 pub(crate) skip_interrupt: bool,
37 pub(crate) int_mode: IntMode,
39 active_prefix: Prefix,
40}
41
42impl Default for Z80 {
43 fn default() -> Self {
44 Self {
45 regs: Regs::default(),
46 halted: false,
47 skip_interrupt: false,
48 int_mode: IntMode::Im0,
49 active_prefix: Prefix::None,
50 }
51 }
52}
53
54impl Z80 {
55 #[inline]
57 pub(crate) fn fetch_byte(&mut self, bus: &mut impl Z80Bus, clk: usize) -> u8 {
58 let addr = self.regs.get_pc();
59 self.regs.inc_pc();
60 bus.read(addr, clk)
61 }
62
63 #[inline]
65 pub(crate) fn fetch_word(&mut self, bus: &mut impl Z80Bus, clk: usize) -> u16 {
66 let (hi_addr, lo_addr);
67 lo_addr = self.regs.get_pc();
68 let lo = bus.read(lo_addr, clk);
69 hi_addr = self.regs.inc_pc();
70 let hi = bus.read(hi_addr, clk);
71 self.regs.inc_pc();
72 u16::from_le_bytes([lo, hi])
73 }
74
75 pub fn is_halted(&self) -> bool {
77 self.halted
78 }
79
80 pub fn get_im(&self) -> IntMode {
82 self.int_mode
83 }
84
85 pub fn set_im(&mut self, value: u8) {
87 assert!(value < 3);
88 self.int_mode = match value {
89 0 => IntMode::Im0,
90 1 => IntMode::Im1,
91 2 => IntMode::Im2,
92 _ => unreachable!(),
93 }
94 }
95
96 pub fn pop_pc_from_stack(&mut self, bus: &mut impl Z80Bus) {
99 execute_pop_16(self, bus, RegName16::PC, 0);
100 }
101
102 pub fn push_pc_to_stack(&mut self, bus: &mut impl Z80Bus) {
105 execute_push_16(self, bus, RegName16::PC, 0);
106 }
107
108 fn handle_interrupt(&mut self, bus: &mut impl Z80Bus) {
109 if bus.nmi_active() {
110 self.regs.clear_q();
112 if self.halted {
114 bus.halt(false);
115 self.halted = false;
116 self.regs.inc_pc();
117 }
118 bus.wait_loop(self.regs.get_pc(), 5);
120 self.regs.set_iff1(false);
121 execute_push_16(self, bus, RegName16::PC, 3);
123 self.regs.set_pc(0x0066);
124
125 self.regs.set_mem_ptr(self.regs.get_pc());
127
128 self.regs.inc_r();
129 } else if bus.int_active() && self.regs.get_iff1() {
131 self.regs.clear_q();
133 if self.halted {
135 bus.halt(false);
136 self.halted = false;
137 self.regs.inc_pc();
138 }
139 self.regs.inc_r();
140 self.regs.set_iff1(false);
141 self.regs.set_iff2(false);
142 match self.int_mode {
143 IntMode::Im0 | IntMode::Im1 => {
145 execute_push_16(self, bus, RegName16::PC, 3);
146 self.regs.set_pc(0x0038);
147
148 bus.wait_internal(7);
150 }
151 IntMode::Im2 => {
153 execute_push_16(self, bus, RegName16::PC, 3);
154 let addr = (((self.regs.get_i() as u16) << 8) & 0xFF00)
156 | ((bus.read_interrupt() as u16) & 0x00FF);
157 let addr = bus.read_word(addr, 3);
158 self.regs.set_pc(addr);
159 bus.wait_internal(7);
160 }
162 }
163 self.regs.set_mem_ptr(self.regs.get_pc());
165 }
166 }
167
168 pub fn emulate(&mut self, bus: &mut impl Z80Bus) {
170 if !self.skip_interrupt {
172 self.handle_interrupt(bus);
173 } else {
174 self.skip_interrupt = false;
176 };
177
178 let before_execute_opcode = |cpu: &mut Self| {
180 cpu.regs.step_q();
183 };
184
185 let byte1 = if self.active_prefix != Prefix::None {
186 let tmp = self.active_prefix.to_byte().unwrap();
187 self.active_prefix = Prefix::None;
188 tmp
189 } else {
190 self.regs.inc_r();
191 self.fetch_byte(bus, 4)
192 };
193 let prefix_hi = Prefix::from_byte(byte1);
194 if prefix_hi != Prefix::None {
195 match prefix_hi {
196 prefix_single @ Prefix::DD | prefix_single @ Prefix::FD => {
197 let byte2 = self.fetch_byte(bus, 4);
198 self.regs.inc_r();
199 let prefix_lo = Prefix::from_byte(byte2);
200 match prefix_lo {
201 Prefix::DD | Prefix::ED | Prefix::FD => {
202 self.active_prefix = prefix_lo;
203 self.skip_interrupt = true;
204 }
205 Prefix::CB => {
206 before_execute_opcode(self);
207 execute_bits(self, bus, prefix_single);
208 }
209 Prefix::None => {
210 let opcode = Opcode::from_byte(byte2);
211 before_execute_opcode(self);
212 execute_normal(self, bus, opcode, prefix_single);
213 }
214 };
215 }
216 Prefix::CB => {
217 before_execute_opcode(self);
219 execute_bits(self, bus, Prefix::None);
220 }
221 Prefix::ED => {
222 let byte2 = self.fetch_byte(bus, 4);
223 self.regs.inc_r();
224 let opcode = Opcode::from_byte(byte2);
225 before_execute_opcode(self);
226 execute_extended(self, bus, opcode);
227 }
228 _ => unreachable!(),
229 };
230 } else {
231 let opcode = Opcode::from_byte(byte1);
232 before_execute_opcode(self);
233 execute_normal(self, bus, opcode, Prefix::None);
234 };
235 bus.pc_callback(self.regs.get_pc());
237 }
238}