crustacean_6502_emulator/src/emulator/addressing_modes.rs

101 lines
2.4 KiB
Rust

use std::convert::{From, Into};
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
pub struct Address(pub usize);
impl From<usize> for Address {
fn from(v: usize) -> Self {
if v > 0xFFFF {
panic!("Address is bigger than 0x10000 (Got 0x{:04X})", v);
}
Self(v)
}
}
impl From<i32> for Address {
fn from(v: i32) -> Self {
if v < 0 || v > 0xFFFF {
panic!("Can't use {}i32 as address", v);
}
Address((v & 0xFFFF) as usize)
}
}
impl From<u16> for Address {
fn from(v: u16) -> Self {
Self(v as usize)
}
}
impl From<u8> for Address {
fn from(v: u8) -> Self {
Address((v as usize) & 0xFF)
}
}
impl Into<usize> for Address {
fn into(self) -> usize {
*self & 0xFFFF
}
}
impl Into<u16> for Address {
fn into(self) -> u16 {
(*self & 0xFFFF) as u16
}
}
impl std::ops::Deref for Address {
type Target = usize;
fn deref(&self) -> &usize {
&self.0
}
}
impl std::ops::DerefMut for Address {
fn deref_mut(&mut self) -> &mut usize {
&mut self.0
}
}
impl std::ops::Add for Address {
type Output = Self;
fn add(self, rhs: Self) -> Self {
let result = *self + *rhs;
if result > 0xFFFF {
panic!(
"Resulting op between Address and 0x{:04X} is bigger than 0xFFFF",
*rhs
);
}
Address(result)
}
}
impl Address {
pub fn same_page_add<I: Into<usize>>(self, rhs: I) -> Self {
let rhs = rhs.into() & 0x00FF;
let hi = *self & 0xFF00;
let lo = (*self + rhs) & 0xFF;
Address(hi | lo)
}
pub fn next(&self) -> Self {
Address(self.0 + 1)
}
}
pub fn get_size(addr_mode: AddressingMode) -> usize {
OP_SIZES[addr_mode as usize]
}
//A,abs,absX,absY,imm,impl,ind,indX,indY,rel,zpg,zpgX,zpgY
//1, 3, 3, 3, 2, 1, 3, 2, 2, 2, 2, 2, 2
pub static OP_SIZES: [usize; 13] = [1, 3, 3, 3, 2, 1, 3, 2, 2, 2, 2, 2, 2];
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum AddressingMode {
A = 0, // LSR A
ABS, // LDA $1234
ABSX, // STA $3000,X
ABSY, // AND $4000,Y
IMM, // LDA #$10
IMPL, // CLC
IND, // JMP ($FFFC)
INDX, // LDA ($40,X)
INDY, // LDA ($40),Y
REL, // LABEL // +4
ZPG, // LDA $10
ZPGX, // LDA $10,X
ZPGY, // LDA $10,Y
}