flow.rsannotatedflow.rssource420 lines · 12.2 KB · raw
1#[allow(clippy::wildcard_imports)]
2use super::*;
3use jgenesis_common::num::U16Ext;
4
5macro_rules! impl_branch {
6    ($name:ident $(, $flag:ident == $value:expr)?) => {
7        pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) {
8            match cpu.state.cycle {
9                1 => {
10                    cpu.state.t0 = fetch_operand(cpu, bus);
11
12                    // Check if branch should be taken; skip rest of instruction if not
13                    $(
14                        if cpu.registers.psw.$flag != $value {
15                            cpu.state.cycle = 0;
16                        }
17                    )?
18                }
19                2 => {
20                    bus.idle();
21                }
22                3 => {
23                    cpu.final_cycle();
24                    bus.idle();
25
26                    cpu.registers.pc = cpu.registers.pc.wrapping_add(cpu.state.t0 as i8 as u16);
27                }
28                _ => invalid_cycle!(cpu)
29            }
30        }
31    }
32}
33
34impl_branch!(bra);
35impl_branch!(beq, zero == true);
36impl_branch!(bne, zero == false);
37impl_branch!(bcs, carry == true);
38impl_branch!(bcc, carry == false);
39impl_branch!(bvs, overflow == true);
40impl_branch!(bvc, overflow == false);
41impl_branch!(bmi, negative == true);
42impl_branch!(bpl, negative == false);
43
44macro_rules! impl_branch_memory_bit {
45    ($name:ident, bit == $value:expr) => {
46        pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B, bit: u8) {
47            match cpu.state.cycle {
48                1 => {
49                    cpu.state.t0 = fetch_operand(cpu, bus);
50                }
51                2 => {
52                    let address = u16::from_le_bytes([cpu.state.t0, cpu.direct_page_msb()]);
53                    cpu.state.t1 = bus.read(address);
54                }
55                3 | 5 => {
56                    bus.idle();
57                }
58                4 => {
59                    cpu.state.t2 = fetch_operand(cpu, bus);
60
61                    // Skip rest of instruction if specified bit is not set/clear
62                    if cpu.state.t1.bit(bit) != $value {
63                        cpu.state.cycle = 0;
64                    }
65                }
66                6 => {
67                    cpu.final_cycle();
68                    bus.idle();
69
70                    cpu.registers.pc = cpu.registers.pc.wrapping_add(cpu.state.t2 as i8 as u16);
71                }
72                _ => invalid_cycle!(cpu),
73            }
74        }
75    };
76}
77
78impl_branch_memory_bit!(bbs, bit == true);
79impl_branch_memory_bit!(bbc, bit == false);
80
81pub(crate) fn cbne_dp<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) {
82    match cpu.state.cycle {
83        1 => {
84            cpu.state.t0 = fetch_operand(cpu, bus);
85        }
86        2 => {
87            let address = u16::from_le_bytes([cpu.state.t0, cpu.direct_page_msb()]);
88            cpu.state.t1 = bus.read(address);
89        }
90        3 | 5 => {
91            bus.idle();
92        }
93        4 => {
94            cpu.state.t2 = fetch_operand(cpu, bus);
95
96            // Skip rest of instruction if A == (dp)
97            if cpu.registers.a == cpu.state.t1 {
98                cpu.state.cycle = 0;
99            }
100        }
101        // 5: Idle
102        6 => {
103            cpu.final_cycle();
104            bus.idle();
105
106            cpu.registers.pc = cpu.registers.pc.wrapping_add(cpu.state.t2 as i8 as u16);
107        }
108        _ => invalid_cycle!(cpu),
109    }
110}
111
112pub(crate) fn cbne_dpx<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) {
113    match cpu.state.cycle {
114        1 => {
115            cpu.state.t0 = fetch_operand(cpu, bus);
116        }
117        2 | 4 | 6 => {
118            bus.idle();
119        }
120        3 => {
121            let address_lsb = cpu.state.t0.wrapping_add(cpu.registers.x);
122            let address = u16::from_le_bytes([address_lsb, cpu.direct_page_msb()]);
123            cpu.state.t1 = bus.read(address);
124        }
125        // 4: Idle
126        5 => {
127            cpu.state.t2 = fetch_operand(cpu, bus);
128
129            // Skip rest of instruction if A == (dp+X)
130            if cpu.registers.a == cpu.state.t1 {
131                cpu.state.cycle = 0;
132            }
133        }
134        // 6: Idle
135        7 => {
136            cpu.final_cycle();
137            bus.idle();
138
139            cpu.registers.pc = cpu.registers.pc.wrapping_add(cpu.state.t2 as i8 as u16);
140        }
141        _ => invalid_cycle!(cpu),
142    }
143}
144
145pub(crate) fn dbnz_dp<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) {
146    match cpu.state.cycle {
147        1 => {
148            cpu.state.t0 = fetch_operand(cpu, bus);
149        }
150        2 => {
151            let address = u16::from_le_bytes([cpu.state.t0, cpu.direct_page_msb()]);
152            cpu.state.t1 = bus.read(address);
153        }
154        3 => {
155            let address = u16::from_le_bytes([cpu.state.t0, cpu.direct_page_msb()]);
156            bus.write(address, cpu.state.t1.wrapping_sub(1));
157        }
158        4 => {
159            cpu.state.t2 = fetch_operand(cpu, bus);
160
161            // Skip rest of instruction if --(dp) == 0
162            if cpu.state.t1 == 1 {
163                cpu.state.cycle = 0;
164            }
165        }
166        5 => {
167            bus.idle();
168        }
169        6 => {
170            cpu.final_cycle();
171            bus.idle();
172
173            cpu.registers.pc = cpu.registers.pc.wrapping_add(cpu.state.t2 as i8 as u16);
174        }
175        _ => invalid_cycle!(cpu),
176    }
177}
178
179pub(crate) fn dbnz_y<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) {
180    match cpu.state.cycle {
181        1 | 2 | 4 => {
182            bus.idle();
183        }
184        3 => {
185            cpu.state.t1 = fetch_operand(cpu, bus);
186
187            // Skip rest of instruction if --Y == 0
188            cpu.registers.y = cpu.registers.y.wrapping_sub(1);
189            if cpu.registers.y == 0 {
190                cpu.state.cycle = 0;
191            }
192        }
193        // 4: Idle
194        5 => {
195            cpu.final_cycle();
196            bus.idle();
197
198            cpu.registers.pc = cpu.registers.pc.wrapping_add(cpu.state.t1 as i8 as u16);
199        }
200        _ => invalid_cycle!(cpu),
201    }
202}
203
204pub(crate) fn jmp_abs<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) {
205    match cpu.state.cycle {
206        1 => {
207            cpu.state.t0 = fetch_operand(cpu, bus);
208        }
209        2 => {
210            cpu.final_cycle();
211
212            let address_msb = fetch_operand(cpu, bus);
213            cpu.registers.pc = u16::from_le_bytes([cpu.state.t0, address_msb]);
214        }
215        _ => invalid_cycle!(cpu),
216    }
217}
218
219pub(crate) fn jmp_absx_ind<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) {
220    match cpu.state.cycle {
221        1 => {
222            cpu.state.t0 = fetch_operand(cpu, bus);
223        }
224        2 => {
225            cpu.state.t1 = fetch_operand(cpu, bus);
226        }
227        3 => {
228            bus.idle();
229        }
230        4 => {
231            let address = u16::from_le_bytes([cpu.state.t0, cpu.state.t1])
232                .wrapping_add(cpu.registers.x.into());
233            cpu.state.t2 = bus.read(address);
234        }
235        5 => {
236            cpu.final_cycle();
237
238            let address = u16::from_le_bytes([cpu.state.t0, cpu.state.t1])
239                .wrapping_add(cpu.registers.x.into())
240                .wrapping_add(1);
241            let jump_address_msb = bus.read(address);
242            cpu.registers.pc = u16::from_le_bytes([cpu.state.t2, jump_address_msb]);
243        }
244        _ => invalid_cycle!(cpu),
245    }
246}
247
248pub(crate) fn call<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) {
249    match cpu.state.cycle {
250        1 => {
251            cpu.state.t0 = fetch_operand(cpu, bus);
252        }
253        2 => {
254            cpu.state.t1 = fetch_operand(cpu, bus);
255        }
256        3 | 6 => {
257            bus.idle();
258        }
259        4 => {
260            bus.write(cpu.stack_pointer(), cpu.registers.pc.msb());
261            cpu.registers.sp = cpu.registers.sp.wrapping_sub(1);
262        }
263        5 => {
264            bus.write(cpu.stack_pointer(), cpu.registers.pc.lsb());
265            cpu.registers.sp = cpu.registers.sp.wrapping_sub(1);
266        }
267        // 6: Idle
268        7 => {
269            cpu.final_cycle();
270            bus.idle();
271
272            cpu.registers.pc = u16::from_le_bytes([cpu.state.t0, cpu.state.t1]);
273        }
274        _ => invalid_cycle!(cpu),
275    }
276}
277
278pub(crate) fn pcall<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) {
279    match cpu.state.cycle {
280        1 => {
281            cpu.state.t0 = fetch_operand(cpu, bus);
282        }
283        2 => {
284            bus.idle();
285        }
286        3 => {
287            bus.write(cpu.stack_pointer(), cpu.registers.pc.msb());
288            cpu.registers.sp = cpu.registers.sp.wrapping_sub(1);
289        }
290        4 => {
291            bus.write(cpu.stack_pointer(), cpu.registers.pc.lsb());
292            cpu.registers.sp = cpu.registers.sp.wrapping_sub(1);
293        }
294        5 => {
295            cpu.final_cycle();
296            bus.idle();
297
298            cpu.registers.pc = u16::from_le_bytes([cpu.state.t0, 0xFF]);
299        }
300        _ => invalid_cycle!(cpu),
301    }
302}
303
304pub(crate) fn tcall<B: BusInterface>(cpu: &mut Spc700, bus: &mut B, n: u16) {
305    match cpu.state.cycle {
306        1 => {
307            // Dummy read
308            bus.read(cpu.registers.pc);
309        }
310        2 | 5 => {
311            bus.idle();
312        }
313        3 => {
314            bus.write(cpu.stack_pointer(), cpu.registers.pc.msb());
315            cpu.registers.sp = cpu.registers.sp.wrapping_sub(1);
316        }
317        4 => {
318            bus.write(cpu.stack_pointer(), cpu.registers.pc.lsb());
319            cpu.registers.sp = cpu.registers.sp.wrapping_sub(1);
320        }
321        // 5: Idle
322        6 => {
323            let address = 0xFFC0 + 2 * (15 - n);
324            cpu.state.t0 = bus.read(address);
325        }
326        7 => {
327            cpu.final_cycle();
328
329            let address = 0xFFC1 + 2 * (15 - n);
330            let jump_address_msb = bus.read(address);
331            cpu.registers.pc = u16::from_le_bytes([cpu.state.t0, jump_address_msb]);
332        }
333        _ => invalid_cycle!(cpu),
334    }
335}
336
337pub(crate) fn ret<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) {
338    match cpu.state.cycle {
339        1 | 2 => {
340            bus.idle();
341        }
342        3 => {
343            cpu.registers.sp = cpu.registers.sp.wrapping_add(1);
344            cpu.state.t0 = bus.read(cpu.stack_pointer());
345        }
346        4 => {
347            cpu.final_cycle();
348
349            cpu.registers.sp = cpu.registers.sp.wrapping_add(1);
350            let pc_msb = bus.read(cpu.stack_pointer());
351            cpu.registers.pc = u16::from_le_bytes([cpu.state.t0, pc_msb]);
352        }
353        _ => invalid_cycle!(cpu),
354    }
355}
356
357pub(crate) fn reti<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) {
358    match cpu.state.cycle {
359        1 | 2 => {
360            bus.idle();
361        }
362        3 => {
363            cpu.registers.sp = cpu.registers.sp.wrapping_add(1);
364            cpu.registers.psw = bus.read(cpu.stack_pointer()).into();
365        }
366        4 => {
367            cpu.registers.sp = cpu.registers.sp.wrapping_add(1);
368            cpu.state.t0 = bus.read(cpu.stack_pointer());
369        }
370        5 => {
371            cpu.final_cycle();
372
373            cpu.registers.sp = cpu.registers.sp.wrapping_add(1);
374            let pc_msb = bus.read(cpu.stack_pointer());
375            cpu.registers.pc = u16::from_le_bytes([cpu.state.t0, pc_msb]);
376        }
377        _ => invalid_cycle!(cpu),
378    }
379}
380
381const BRK_VECTOR: u16 = 0xFFDE;
382
383pub(crate) fn brk<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) {
384    match cpu.state.cycle {
385        1 | 5 => {
386            bus.idle();
387        }
388        2 => {
389            bus.write(cpu.stack_pointer(), cpu.registers.pc.msb());
390            cpu.registers.sp = cpu.registers.sp.wrapping_sub(1);
391        }
392        3 => {
393            bus.write(cpu.stack_pointer(), cpu.registers.pc.lsb());
394            cpu.registers.sp = cpu.registers.sp.wrapping_sub(1);
395        }
396        4 => {
397            bus.write(cpu.stack_pointer(), cpu.registers.psw.into());
398            cpu.registers.sp = cpu.registers.sp.wrapping_sub(1);
399        }
400        // 5: Idle
401        6 => {
402            cpu.state.t0 = bus.read(BRK_VECTOR);
403        }
404        7 => {
405            cpu.final_cycle();
406
407            let pc_msb = bus.read(BRK_VECTOR + 1);
408            cpu.registers.pc = u16::from_le_bytes([cpu.state.t0, pc_msb]);
409            cpu.registers.psw.break_flag = true;
410            cpu.registers.psw.interrupt_enabled = false;
411        }
412        _ => invalid_cycle!(cpu),
413    }
414}
415
416pub(crate) fn stop<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) {
417    cpu.final_cycle();
418    bus.idle();
419    cpu.state.stopped = true;
420}