Orthogonal AddressingMode handling; implement all addressing modes for ADC, LDA, LDX, LDY

We can factor out the addressing-mode-processing code that's common to all instructions by letting the addressing modes have different kinds of output.

```rust
pub enum AMOut /* poorly named, sorry */ {
    UseImplied,
    UseImmediate(u8),
    UseRelative(i8),
    UseAddress(Address),
}

impl AddressingMode {
    pub fn process(self, machine: &Machine, arr: &[u8]) -> AMOut {
        // ...
    }
}
```

This means we only need to handle 2 cases for ADC when executing the instruction. Either it operates on an address (no matter how we got that address--that's the AddressingMode's job), or it operates on an immediate value:

```rust
impl Machine {
    pub fn execute_instruction(&mut self, decoded_instr: DecodedInstr) {
        match decoded_instr {
            (ADC, UseImmediate(val)) => {
                self.add_with_carry(val as i8);
            },
            (ADC, UseAddress(addr)) => {
                let val = self.memory.get_byte(addr) as i8;
                self.add_with_carry(val);
            },

            (LDA, UseImmediate(val)) => {
                self.load_accumulator(val as i8);
            },
            (LDA, UseAddress(addr)) => {
                let val = self.memory.get_byte(addr);
                self.load_accumulator(val as i8);
            },

            (_, _) => {
                // could fail! here
            }
        }
    }

    // ...
}
```

The logic that's common to LDA and ADC could be factored out more, but it's a start.