c64_assembler/memory/
address_mode.rs

1use crate::{validator::AssemblerResult, Application};
2
3use super::{label::AddressReference, Address, ZeroPage};
4
5#[derive(Clone, Debug, Default, PartialEq)]
6pub enum AddressMode {
7    #[default]
8    Implied,
9    Accumulator,
10    Immediate(Immediate),
11    Absolute(AddressReference),
12    AbsoluteX(AddressReference),
13    AbsoluteY(AddressReference),
14    Relative(AddressReference),
15    Indirect(AddressReference),
16    IndexedIndirect(AddressReference),
17    IndirectIndexed(AddressReference),
18}
19
20fn is_zeropage(application: &Application, address_reference: &AddressReference) -> AssemblerResult<bool> {
21    Ok(application.lookup_address(&address_reference.name)?.is_zeropage())
22}
23
24impl AddressMode {
25    /// Total number of bytes the instruction occupies on a 6502.
26    ///
27    /// Application parameter is used to identify if an instruction should use its zeropage variant.
28    pub fn byte_size(&self, application: &Application) -> AssemblerResult<Address> {
29        match &self {
30            AddressMode::Implied | AddressMode::Accumulator => Ok(1),
31            AddressMode::Relative(_) | AddressMode::Immediate(_) => Ok(2),
32            AddressMode::Absolute(address_reference)
33            | AddressMode::AbsoluteX(address_reference)
34            | AddressMode::AbsoluteY(address_reference) => {
35                if is_zeropage(application, address_reference)? {
36                    Ok(2)
37                } else {
38                    Ok(3)
39                }
40            }
41            AddressMode::Indirect(_address_reference) => Ok(3),
42            AddressMode::IndexedIndirect(_address_reference) | AddressMode::IndirectIndexed(_address_reference) => {
43                Ok(2)
44            }
45        }
46    }
47}
48
49#[derive(Clone, Debug, PartialEq)]
50pub enum Immediate {
51    Byte(u8),
52    Low(AddressReference),
53    High(AddressReference),
54}