Skip to main content

rustysnes_cpu/
addr.rs

1//! Addressing-mode resolution for the 65C816.
2//!
3//! Each mode resolves to an effective 24-bit address (and, where relevant, whether an indexed
4//! access crossed a 256-byte page boundary — the documented `+1` cycle penalty). Operand
5//! bytes are fetched from the program bank (`PBR`) by the executor's instruction-fetch path.
6//!
7//! Bank handling follows the hardware rules: direct-page and stack-relative effective
8//! addresses live in bank `0`; `(dp),Y` / `[dp]` / `abs,X` etc. add the index/`DBR` and may
9//! carry into the next bank for the long forms. See `docs/cpu.md` ("Addressing modes").
10
11/// The enumerated 65C816 addressing modes the executor dispatches on.
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum Mode {
14    /// Immediate operand whose width follows `M` (memory/accumulator modes).
15    ImmediateM,
16    /// Immediate operand whose width follows `X` (index modes).
17    ImmediateX,
18    /// Direct page: `D + dp`.
19    Direct,
20    /// Direct page indexed by `X`: `D + dp + X`.
21    DirectX,
22    /// Direct page indexed by `Y`: `D + dp + Y`.
23    DirectY,
24    /// Direct indirect: `[D + dp]` → 16-bit pointer in bank `DBR`.
25    DirectIndirect,
26    /// Direct indexed indirect: `[D + dp + X]` → pointer in bank `DBR`.
27    DirectXIndirect,
28    /// Direct indirect indexed: `[D + dp]` + `Y`, base in bank `DBR`.
29    DirectIndirectY,
30    /// Direct indirect long: `[D + dp]` → 24-bit pointer.
31    DirectIndirectLong,
32    /// Direct indirect long indexed: `[D + dp]` (24-bit) + `Y`.
33    DirectIndirectLongY,
34    /// Absolute: `DBR:operand`.
35    Absolute,
36    /// Absolute indexed by `X`: `DBR:operand + X`.
37    AbsoluteX,
38    /// Absolute indexed by `Y`: `DBR:operand + Y`.
39    AbsoluteY,
40    /// Absolute long: 24-bit operand.
41    AbsoluteLong,
42    /// Absolute long indexed by `X`: 24-bit operand + `X`.
43    AbsoluteLongX,
44    /// Stack relative: `S + sr` (bank `0`).
45    StackRelative,
46    /// Stack relative indirect indexed: `[S + sr]` (bank `0`) + `Y`, base bank `DBR`.
47    StackRelativeIndirectY,
48}
49
50/// A resolved effective address plus the page-cross flag used for the indexed `+1` penalty.
51#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub struct Effective {
53    /// The 24-bit effective address (low byte of a multi-byte operand).
54    pub addr: u32,
55    /// Whether an indexed mode crossed a 256-byte page boundary.
56    pub page_cross: bool,
57    /// Whether the operand lives in the bank-`0` direct-page / stack window, where a 16-bit
58    /// access wraps its high-byte address within `$0000..=$FFFF` instead of carrying into the
59    /// next bank. Set for direct-page and stack-relative modes; clear for absolute/long modes.
60    pub bank0_wrap: bool,
61}