rustynes_cpu/bus.rs
1//! CPU `Bus` trait.
2//!
3//! Per `docs/cpu-6502.md` §Interfaces. Phase 1 keeps the surface minimal:
4//! address-fanout reads/writes plus interrupt polling. The DMA halt mechanism
5//! lands when the APU does (Phase 3), and the cycle-level tick callback is
6//! enough to drive `cpu_timing_test` and golden-log compares without the full
7//! lockstep scheduler.
8
9use crate::scheduler::M2Phase;
10
11/// Address-space bus seen by the CPU.
12///
13/// The CPU borrows `&mut Bus` for the duration of an instruction; the bus
14/// fans the access out to RAM, PPU registers, APU registers, controllers,
15/// and the cartridge's mapper.
16pub trait Bus {
17 /// Read a byte at `addr`.
18 fn cpu_read(&mut self, addr: u16) -> u8;
19
20 /// Write `value` to `addr`.
21 fn cpu_write(&mut self, addr: u16, value: u8);
22
23 /// Edge-triggered NMI poll. Returns `true` exactly once per high-to-low
24 /// transition of the NMI line; subsequent calls return `false` until the
25 /// next transition.
26 fn poll_nmi(&mut self) -> bool {
27 false
28 }
29
30 /// Level-sensitive IRQ. Sampled by the CPU on every instruction's
31 /// second-to-last cycle; only honored when the CPU's I flag is clear.
32 fn poll_irq(&mut self) -> bool {
33 false
34 }
35
36 /// Phase-aware level-sensitive IRQ sample.
37 ///
38 /// Returns the IRQ line as seen at the requested half of the 6502
39 /// cycle. Phase-aware bus implementations override this to expose
40 /// the M2-low vs M2-high asymmetry the C1 IRQ-timing rework relies
41 /// on (see `docs/adr/0002-irq-timing-coordination.md`); the default
42 /// impl simply delegates to [`Bus::poll_irq`], so legacy / test bus
43 /// stubs that don't model the phase distinction stay correct without
44 /// needing to import [`M2Phase`].
45 ///
46 /// Phase B3 of the C1 rework: `Cpu::idle_tick` calls
47 /// `bus.poll_irq_at_phase(M2Phase::High)` — semantically identical
48 /// to the previous `bus.poll_irq()` call because the production
49 /// [`crate::Bus`] impl on `LockstepBus` takes its M2-high snapshot
50 /// at the same end-of-cycle point the historical `poll_irq` query
51 /// fired from.
52 fn poll_irq_at_phase(&mut self, phase: M2Phase) -> bool {
53 let _ = phase;
54 self.poll_irq()
55 }
56
57 /// Called once per CPU cycle consumed. Used by the scheduler to advance
58 /// the PPU/APU in lockstep (Phase 2+) and by the test harness to count
59 /// cycles for golden-log compare.
60 fn on_cpu_cycle(&mut self) {}
61
62 /// φ1 (pre-access) half of one CPU cycle, for the C1 access-reorder
63 /// axis attempt 17. Called BEFORE the bus access in
64 /// `Cpu::read1` / `Cpu::write1` when the
65 /// `cpu-c1-attempt-17-access-reorder` feature is enabled.
66 ///
67 /// On the production [`crate::Bus`] (`LockstepBus`), this ticks
68 /// PPU sub-dot 0 (1 PPU dot) and captures the M2-low IRQ
69 /// snapshot. Default impl is a no-op so legacy / test buses
70 /// don't accidentally advance state when paired with the φ2
71 /// default (which calls [`Bus::on_cpu_cycle`] to do all the
72 /// work).
73 fn cpu_cycle_phi1(&mut self) {}
74
75 /// φ2 (post-access) half of one CPU cycle. Called AFTER the
76 /// bus access in `Cpu::read1` / `Cpu::write1`
77 /// when the `cpu-c1-attempt-17-access-reorder` feature is
78 /// enabled.
79 ///
80 /// On the production `LockstepBus`, this ticks PPU sub-dots 1+2
81 /// (2 PPU dots), increments the bus-side cycle counter, fires
82 /// `notify_cpu_cycle` + `tick_with_external`, and captures the
83 /// M2-high IRQ snapshot.
84 ///
85 /// The default impl delegates to [`Bus::on_cpu_cycle`] so
86 /// legacy / test buses keep their current behaviour: φ1 is a
87 /// no-op, φ2 does all the work, same total per-cycle work as a
88 /// single `on_cpu_cycle` call.
89 fn cpu_cycle_phi2(&mut self) {
90 self.on_cpu_cycle();
91 }
92
93 /// Notify the bus that the CPU is about to perform an interrupt
94 /// vector fetch from `vector` (`$FFFE` for IRQ/BRK, `$FFFA` for NMI,
95 /// or `$FFFA` if an IRQ/BRK service sequence was hijacked by an NMI
96 /// edge during cycles 1..=5 of the service sequence). `is_nmi` is
97 /// `true` for an NMI service entry and `false` for an IRQ or BRK
98 /// service entry (so the bus can distinguish hijack from a clean
99 /// NMI even when the vector is the same).
100 ///
101 /// Default impl is a no-op; production buses with the
102 /// `irq-timing-trace` feature override this to emit a
103 /// [`ServiceEvent`] into the IRQ trace fixture. Phase 1.2 of
104 /// Track C1 attempt 14 added this method to close the schema gap
105 /// with Mesen2's `emu.eventType.irq` / `emu.eventType.nmi` oracle.
106 ///
107 /// [`ServiceEvent`]: # "see rustynes_core::irq_trace::ServiceEvent"
108 fn notify_irq_service(&mut self, vector: u16, is_nmi: bool) {
109 let _ = vector;
110 let _ = is_nmi;
111 }
112
113 /// Cumulative bus-side cycle counter.
114 ///
115 /// On the production `LockstepBus`, this is `self.cycle` —
116 /// the total number of CPU cycles the bus has ticked, INCLUDING
117 /// DMC DMA halt + dummy + alignment + transfer cycles (which
118 /// the CPU's own `Cpu::cycles` field does NOT count because
119 /// they advance through `bus.tick_one_cpu_cycle()` rather than
120 /// the CPU's `idle_tick`).
121 ///
122 /// Used by the SH* unstable-store family (`SHA / SHX / SHY /
123 /// SHS / TAS`) to detect when DMC DMA interrupted the
124 /// instruction's dummy-read cycle: per Mesen2 `NesCpu.h`
125 /// `SyaSxaAxa` (lines 716-745), if the dummy read consumed
126 /// more than 1 bus cycle, a DMA fired, and the value written
127 /// is `valueReg` un-ANDed with the H+1 byte (the DMA pulled
128 /// the bus low / corrupted the latch). Mesen2 detects this
129 /// via `_state.CycleCount - cyc > 1` after the dummy read;
130 /// we mirror via `bus.cycle_count() - before > 1`.
131 ///
132 /// Default impl returns `0` for legacy / test bus stubs.
133 fn cycle_count(&self) -> u64 {
134 0
135 }
136
137 /// Most recent value driven onto the **internal** CPU data bus.
138 ///
139 /// The 2A03 silicon has two distinct data buses: the **internal**
140 /// data bus carries CPU instruction fetches, operand reads, ALU
141 /// results, and writes; the **external** data bus is shared with
142 /// the DMC DMA fetch path and is observable via the open-bus
143 /// latch. The two buses are equal on every cycle where the CPU
144 /// drives the bus, but diverge during DMC DMA halt: the DMC
145 /// fetch drives the external bus (the "open bus") while the CPU
146 /// is halted and the internal bus retains its prior value.
147 ///
148 /// Default impl returns `0` for legacy / test bus stubs that do
149 /// not model the distinction. The production `LockstepBus`
150 /// overrides this to expose the latched internal value (mirrored
151 /// from every CPU read but NOT updated by DMC DMA fetches).
152 ///
153 /// Used by the SH* unstable-store family (`SHA / SHX / SHY / SHS
154 /// / TAS`, opcodes `$93 / $9C / $9E / $9F / $9B`) when computing
155 /// the address-high-byte AND-and-write quantity under DMC DMA
156 /// interleaving, and by the `$4015` read path for the bit-5
157 /// open-bus exposure that `CPU Behavior :: Open Bus` Test 9
158 /// brackets. Phase 1 of the v1.0.0-final
159 /// `linked-puzzling-sutherland` brief (see
160 /// `to-dos/phase-6-v1.0.0-final/sprint-6-sh-unstable-stores.md`).
161 ///
162 fn internal_data_bus(&self) -> u8 {
163 0
164 }
165
166 // ================================================================
167 // v2.0 master-clock R1 substrate — clean Bus contract (Phase 1).
168 //
169 // These methods exist ALONGSIDE the legacy lockstep methods above and
170 // are only consulted by the `mc-r1-substrate` CPU loop (Phases 2+). They
171 // carry default impls delegating to the legacy surface so every existing
172 // `Bus` impl (test stubs included) keeps compiling unchanged; the
173 // production `LockstepBus` overrides them with the real master-clock
174 // catch-up. Gated so the default build's trait surface is unchanged.
175 // See `docs/audit/v2.0-master-clock-r1-port-plan-2026-06-03.md`.
176 // ================================================================
177
178 /// Pure address-space read (no per-cycle work). Under R1 the cycle work
179 /// is done by [`Bus::run_ppu_to`] + [`Bus::cpu_clock`], which the CPU
180 /// calls around the access. Default delegates to [`Bus::cpu_read`].
181 fn read(&mut self, addr: u16) -> u8 {
182 self.cpu_read(addr)
183 }
184
185 /// Pure address-space write. Default delegates to [`Bus::cpu_write`].
186 fn write(&mut self, addr: u16, value: u8) {
187 self.cpu_write(addr, value);
188 }
189
190 /// Master clocks per CPU cycle for the cartridge region: NTSC 12, PAL 16,
191 /// Dendy 15 (the master-clock unit is shared with [`Bus::run_ppu_to`]'s
192 /// `ppu_divider`, so per CPU cycle the PPU advances `cpu_divider /
193 /// ppu_divider` dots — 3:1 NTSC, 3.2:1 PAL, 3:1 Dendy). The R1 CPU loop
194 /// advances `master_clock` and derives its read/write split off this. The
195 /// default (12) keeps test stubs + the non-regioned path on NTSC; the
196 /// `LockstepBus` overrides from the cartridge region.
197 fn cpu_divider(&self) -> u64 {
198 12
199 }
200
201 /// Catch the PPU up to `target` master clocks (Mesen `NesPpu::Run` /
202 /// `TetaNES` `clock_to`). Ticks whole PPU dots while
203 /// `ppu_clock + ppu_divider <= target`. Called by the R1 CPU loop in
204 /// BOTH halves of each access (the double catch-up). Default no-op.
205 ///
206 /// `is_post_access` distinguishes WHICH half of the CPU cycle this
207 /// catch-up belongs to: `false` for the pre-access half (called from
208 /// `Cpu::start_cycle`, before the bus access — mirrors Mesen's
209 /// `StartCpuCycle`), `true` for the post-access half (called from
210 /// `Cpu::end_cycle`, after the bus access — mirrors `EndCpuCycle`).
211 /// R1c-3 (`mmc3-m2-phase-irq`, default-off experiment): `LockstepBus`
212 /// forwards this as the real M2-phase label on the `PpuBusAdapter` it
213 /// constructs, replacing the previously call-local (and therefore
214 /// almost-always-zero) `sub_dot` counter with a value that actually
215 /// distinguishes the pre-access (M2-low, φ1) and post-access
216 /// (M2-high, φ2) halves for any A12 transition ticked during this
217 /// catch-up. See `docs/adr/0002-irq-timing-coordination.md` and
218 /// `docs/audit/r1r2-per-dot-scheduler-attempt-2026-07-02.md`.
219 fn run_ppu_to(&mut self, target: u64, is_post_access: bool) {
220 let _ = (target, is_post_access);
221 }
222
223 /// One CPU cycle of bus-side work (Mesen `ProcessCpuClock`): APU +
224 /// frame counter + per-cycle mapper hook + bus-side DMA drain + cycle
225 /// counter. The PPU advance is in [`Bus::run_ppu_to`], not here. Default
226 /// delegates to [`Bus::on_cpu_cycle`] (legacy combined per-cycle work).
227 fn cpu_clock(&mut self) {
228 self.on_cpu_cycle();
229 }
230
231 /// F-2: tick ONLY the DMC byte-timer + DMA arm, at END of cycle (called
232 /// from `Cpu::end_cycle` after the access + PPU catch-up). This places the
233 /// DMC fire-phase at main's end-of-cycle position (so `DMASync`'s `$4000`
234 /// open-bus conflict lands), while the rest of the APU (incl. the IRQ line)
235 /// stays on the cycle-start `cpu_clock` tick (so the C1 φ2 IRQ sample is
236 /// unchanged). Default no-op. Pairs with `Apu::set_dmc_driven_externally`.
237 fn cpu_clock_apu_dmc(&mut self) {}
238
239 /// Master clocks consumed by bus-side DMA cycles since the last call,
240 /// then reset to 0. The R1 CPU loop folds this into `master_clock` in
241 /// `end_cycle` so the CPU<->PPU phase stays coherent across a bus-side
242 /// DMA span. Default 0 (no bus-side DMA accounting on test stubs).
243 fn take_dma_mc_consumed(&mut self) -> u64 {
244 0
245 }
246
247 /// Live IRQ line level (mapper IRQ OR APU frame-counter/DMC IRQ). The
248 /// CPU does the I-flag mask + one-cycle `prev_run_irq` delay itself.
249 /// Default `false`; the production bus overrides this.
250 fn irq_level(&self) -> bool {
251 false
252 }
253
254 /// Live /NMI line level (PPU-driven). The CPU does its own edge detect +
255 /// one-cycle `prev_need_nmi` delay. Default `false` (test stubs).
256 fn nmi_level(&self) -> bool {
257 false
258 }
259
260 /// Phase B (interleaved DMC DMA): is a DMC DMA pending and needing cycles?
261 /// The CPU loops on this in `read1`, running one `dmc_dma_step` per R1 cycle
262 /// BEFORE its own read (DMA halts only on read cycles). Default `false`.
263 fn dmc_dma_pending(&self) -> bool {
264 false
265 }
266
267 /// `mc-r1-dmc-load-get-entry`: defer a LOAD whose first-service would be a PUT
268 /// cycle by 1 CPU cycle so it enters on a GET (span-3 hardware load). Gates BOTH
269 /// the read1 loop AND the `idle_tick` loop (`DMASync`'s load fires during NOPs=idle).
270 fn dmc_dma_defer_load_entry(&self) -> bool {
271 false
272 }
273
274 /// Phase B: perform ONE cycle's worth of interleaved DMC DMA bus access
275 /// (halt re-read / sample get), advancing the halt/get state. `halted_addr`
276 /// is the CPU read the DMA is preempting. Default no-op.
277 fn dmc_dma_step(&mut self, halted_addr: u16) {
278 let _ = halted_addr;
279 }
280
281 /// `mc-r1-dmc-idle-halt`: perform one interleaved DMC-DMA cycle during a CPU
282 /// INTERNAL cycle (no instruction read). The bus supplies the held address
283 /// (its last-read bus address) since `idle_tick` has none. Default no-op.
284 fn dmc_dma_step_idle(&mut self) {}
285
286 /// Stage-D (`mc-r1-full-cpu`): is an OAM DMA pending or in flight? The CPU
287 /// loops on this in `read1` (after the DMC loop, DMC-get-before-OAM-get), so
288 /// each OAM cycle runs CPU-driven (wrapped `start_cycle`/`end_cycle`) and
289 /// samples IRQ/NMI via the φ2 pipeline — the surface the bus-burst bypassed.
290 /// Default `false`.
291 fn oam_dma_pending(&self) -> bool {
292 false
293 }
294
295 /// Stage-D: perform ONE cycle of the OAM DMA (set-up on first call from a
296 /// pending `$4014`, then halt/align/read/write per cycle). Does NOT advance
297 /// time — the surrounding `start_cycle`/`end_cycle` do. Default no-op.
298 fn oam_dma_step(&mut self, halted_addr: u16) {
299 let _ = halted_addr;
300 }
301
302 /// Program M (M-2, `mc-r1-dmc-oam-overlap`): is an OAM DMA actually IN FLIGHT
303 /// (started, cycles still owed) — distinct from `oam_dma_pending`, which is
304 /// true for a not-yet-started `$4014` write too. The overlap loop uses this
305 /// to decide whether a DMC halt cycle can SHARE an OAM cycle. Default `false`.
306 fn oam_dma_in_flight(&self) -> bool {
307 false
308 }
309
310 /// W3-Stage-0 (`mc-r1-counter-collapse` boundary realign): may a pending DMC
311 /// DMA join an OAM DMA as an OVERLAP event? Default delegates to
312 /// [`Bus::oam_dma_in_flight`]. Under the counter-collapse flag the bus also
313 /// answers `true` for a `$4014` write that is PENDING but not yet started:
314 /// the end-of-cycle byte-timer shift can surface the DMC arm in the gap
315 /// between the `$4014` write and OAM's first cycle, and routing that arm to
316 /// the standalone `dmc_dma_step` (full unshared span) instead of the overlap
317 /// event is exactly the DMC+OAM idx\[7\] regime-transition error (lockstep
318 /// latches OAM in `drain_dma` BEFORE its DMC-pending check, so the same arm
319 /// overlaps OAM's halt/alignment cycles there).
320 fn oam_dma_overlap_ready(&self) -> bool {
321 self.oam_dma_in_flight()
322 }
323
324 /// Program M (M-2): did the most recent [`Bus::dmc_dma_step`] perform the DMC
325 /// GET (the sample fetch) rather than a halt/dummy/align cycle? The overlap
326 /// loop advances OAM on non-GET (halt) cycles only — the GET steals an OAM
327 /// slot. Default `false`.
328 fn dmc_dma_last_was_get(&self) -> bool {
329 false
330 }
331
332 /// Program M (M-2): advance ONE OAM DMA cycle that is SHARED with a DMC halt
333 /// cycle (the 6502 is RDY-halted by the DMC, but the OAM engine keeps
334 /// consuming its read/write slot on the external bus). Does NOT advance time
335 /// — the surrounding `start_cycle`/`end_cycle` do. Default no-op.
336 fn oam_dma_overlap_cycle(&mut self) {}
337
338 /// Program M (M-2, exact): begin ONE DMC-DMA-during-OAM event, mirroring the
339 /// lockstep `service_dmc_dma_during_oam` prologue. Latches the DMA span + the
340 /// open-bus replay and returns the UNCONDITIONAL halt/dummy/align noop count
341 /// (2 for a short/load DMA, 3 for a reload) — NOT parity-gated. The CPU then
342 /// runs exactly that many [`Bus::dmc_overlap_noop_cycle`]s, one
343 /// [`Bus::dmc_overlap_get_cycle`], and (if OAM still owes) one
344 /// [`Bus::dmc_overlap_realign_cycle`]. `halted_addr` is the CPU read the DMA
345 /// pair is preempting — used as the OAM halt address when the event starts a
346 /// PENDING (not-yet-latched) `$4014` OAM DMA (the counter-collapse boundary
347 /// case; an already-in-flight OAM keeps its own latched halt address).
348 /// Default `0` (no DMC event).
349 fn dmc_overlap_begin(&mut self, halted_addr: u16) -> u32 {
350 let _ = halted_addr;
351 0
352 }
353
354 /// Program M (M-2, exact): one DMC halt/dummy/align cycle that OVERLAPS OAM.
355 /// Replays the held CPU read's side-effect, then (if OAM still owes) advances
356 /// one OAM slot. Mirrors lockstep's noop-loop body (`replay_dma_noop_read` +
357 /// `clock_oam_dma_cycle`) minus the time tick. Default no-op.
358 fn dmc_overlap_noop_cycle(&mut self) {}
359
360 /// Program M (M-2, exact): the DMC GET cycle — owns the memory read; OAM is
361 /// STALLED (does NOT advance). Fetches + delivers the sample and clears the
362 /// DMC-DMA pending state. Mirrors lockstep's get block + the R1
363 /// `dmc_dma_step` GET. Default no-op.
364 fn dmc_overlap_get_cycle(&mut self) {}
365
366 /// Program M (M-2, exact): the post-GET realign stall — ONE extra OAM-stalled
367 /// cycle (OAM does NOT advance) so the next OAM read resumes on a later get,
368 /// mirroring lockstep's `if dma_cycles_owed > 0 { tick }`. The cycle the prior
369 /// per-cycle scaffold was MISSING. Default no-op.
370 fn dmc_overlap_realign_cycle(&mut self) {}
371
372 /// W3-Stage-1 (`mc-r1-dma-unified`): is ANY DMA work pending for the
373 /// unified DMC/OAM engine — a serviceable DMC DMA (pending and not a
374 /// load deferred to its get-cycle entry, the `mc-r1-dmc-load-get-entry`
375 /// rule), a `$4014` OAM DMA awaiting its first cycle, or an OAM transfer
376 /// still in flight? The ONE `Cpu::read1`/`idle_tick` DMA loop spins on
377 /// this, running one [`Bus::unified_dma_cycle`] per CPU cycle (each a
378 /// full R1 cycle: `start_cycle` -> dispatch -> `end_cycle`, so every DMA
379 /// cycle keeps the φ2 IRQ sample — the C1-safe shape). Default `false`.
380 fn unified_dma_pending(&self) -> bool {
381 false
382 }
383
384 /// W3-Stage-1 (`mc-r1-dma-unified`): ONE cycle of the unified DMC/OAM DMA
385 /// engine — a direct port of the `TriCNES` `_6502` per-cycle DMA dispatch
386 /// table (the SINGLE driver standalone DMC, standalone OAM, and the
387 /// overlap all ride), at FLOOR parity for this stage. `halted_addr` is
388 /// the CPU read the DMA is preempting (the parked 6502 address bus).
389 /// Does NOT advance time — the surrounding `start_cycle`/`end_cycle` do.
390 /// Default no-op.
391 fn unified_dma_cycle(&mut self, halted_addr: u16) {
392 let _ = halted_addr;
393 }
394
395 /// W3-Stage-1 (`mc-r1-dma-unified`): one unified-engine DMA cycle during
396 /// a CPU INTERNAL cycle (no instruction read; the bus supplies its held
397 /// last-read address). The unified replacement for
398 /// [`Bus::dmc_dma_step_idle`]. Default no-op.
399 fn unified_dma_cycle_idle(&mut self) {}
400
401 /// accuracycoin-100 Phase 2 (`mc-r1-dmc-abort-cancel`): is a 1-byte
402 /// non-looping implicit DMC-DMA abort matured and awaiting service? The CPU
403 /// consults this at the top of `read1`/`write1`. Default `false`.
404 fn dmc_abort_pending(&self) -> bool {
405 false
406 }
407
408 /// accuracycoin-100 Phase 2: is the upcoming cycle a GET (read) cycle for
409 /// the DMC DMA (`!put_cycle`)? On a get cycle the matured abort runs as a
410 /// 1-cycle DMA (Y=1); on a put cycle (or any CPU write) it does NOT occur
411 /// (Y=0, "the abort will not land on a write cycle"). Default `false`.
412 fn dmc_abort_is_get_cycle(&self) -> bool {
413 false
414 }
415
416 /// accuracycoin-100 Phase 2: service the matured abort as a 1-cycle DMA
417 /// (Y=1) — one halt re-read of `halted_addr`, then clear the abort + the
418 /// pending reload. Called by `read1` only on a get cycle. Default no-op.
419 fn dmc_abort_halt_step(&mut self, halted_addr: u16) {
420 let _ = halted_addr;
421 }
422
423 /// accuracycoin-100 Phase 2: cancel the matured abort with NO halt cycle
424 /// (Y=0) — the abort lands on a write/put cycle so the DMA does not occur.
425 /// Clears the abort + the pending reload. Default no-op.
426 fn dmc_abort_cancel(&mut self) {}
427
428 /// Diagnostic-only hook fired once per R1 CPU cycle from `Cpu::end_cycle`
429 /// (after `handle_interrupts`), so the `irq-timing-trace` tooling can
430 /// record a `CycleRecord` for the R1 access path (which bypasses the
431 /// `LockstepBus` `tick_one_cpu_cycle` push). Default no-op; the production
432 /// bus overrides it only under the `irq-timing-trace` feature, so non-trace
433 /// R1 builds compile this to an empty call.
434 fn trace_end_cycle(&mut self) {}
435
436 /// Diagnostic-only hook fired once per CPU INSTRUCTION from `Cpu::step`
437 /// (at the opcode fetch), with the instruction's `pc` and the cumulative
438 /// CPU cycle count. Lets the `cpu-instr-cycle-trace` tooling diff R1 vs
439 /// default per-instruction to pin the cumulative cycle-count divergence
440 /// (the R1c-1 odd-cycle source). Default no-op.
441 #[cfg(feature = "cpu-instr-cycle-trace")]
442 fn trace_instr(&mut self, _pc: u16, _cpu_cycle: u64) {}
443}