box swap
This commit is contained in:
parent
d97774e97b
commit
f9c938757f
@ -1,16 +1,77 @@
|
|||||||
|
|
||||||
|
/// Represents the various addressing modes of the 6502 CPU.
|
||||||
#[derive(PartialEq, Debug, Copy, Clone)]
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||||
pub enum AddressMode {
|
pub enum AddressMode {
|
||||||
|
/// Implied
|
||||||
|
///
|
||||||
|
/// No operand is needed; the instruction implicitly operates on a register or flag.
|
||||||
|
/// Example: `CLC` (Clear Carry Flag)
|
||||||
Implied,
|
Implied,
|
||||||
|
|
||||||
|
/// Accumulator
|
||||||
|
///
|
||||||
|
/// Operates directly on the accumulator register.
|
||||||
|
/// Example: `ASL A` (Arithmetic Shift Left on Accumulator)
|
||||||
Accumulator,
|
Accumulator,
|
||||||
|
|
||||||
|
/// Immediate
|
||||||
|
///
|
||||||
|
/// Operand is a constant 8-bit value.
|
||||||
|
/// Example: `LDA #$01` loads the value 0x01 into the accumulator.
|
||||||
Immediate,
|
Immediate,
|
||||||
|
|
||||||
|
/// Zero Page
|
||||||
|
///
|
||||||
|
/// Operand is an address in the first 256 bytes of memory (0x0000–0x00FF).
|
||||||
|
/// Example: `LDA $10` reads from address 0x0010.
|
||||||
ZeroPage,
|
ZeroPage,
|
||||||
|
|
||||||
|
/// Zero Page X
|
||||||
|
///
|
||||||
|
/// Zero page address offset by the X register.
|
||||||
|
/// Example: If X = 0x10, `LDA $23,X` reads from 0x33.
|
||||||
ZeroPageX,
|
ZeroPageX,
|
||||||
|
|
||||||
|
/// Zero Page Y
|
||||||
|
///
|
||||||
|
/// Zero page address offset by the Y register.
|
||||||
|
/// Used only by a few instructions like `LDX` and `STX`.
|
||||||
|
/// Example: If Y = 0x10, `LDX $23,Y` reads from 0x33.
|
||||||
ZeroPageY,
|
ZeroPageY,
|
||||||
|
|
||||||
|
/// Absolute
|
||||||
|
///
|
||||||
|
/// Full 16-bit address is provided as the operand.
|
||||||
|
/// Example: `LDA $1234` reads from address 0x1234.
|
||||||
Absolute,
|
Absolute,
|
||||||
|
|
||||||
|
/// Absolute X
|
||||||
|
///
|
||||||
|
/// Absolute address offset by the X register.
|
||||||
|
/// Example: If X = 0x10, `LDA $1234,X` reads from 0x1244.
|
||||||
AbsoluteX,
|
AbsoluteX,
|
||||||
|
|
||||||
|
/// Absolute Y
|
||||||
|
///
|
||||||
|
/// Absolute address offset by the Y register.
|
||||||
|
/// Example: If Y = 0x10, `LDA $1234,Y` reads from 0x1244.
|
||||||
AbsoluteY,
|
AbsoluteY,
|
||||||
|
|
||||||
|
/// Indirect
|
||||||
|
///
|
||||||
|
/// Only used by `JMP`. Operand is a 16-bit address pointing to another 16-bit address.
|
||||||
|
/// Example: `JMP ($1234)` jumps to the address stored at 0x1234/0x1235.
|
||||||
Indirect,
|
Indirect,
|
||||||
|
|
||||||
|
/// Indirect X (Indexed Indirect)
|
||||||
|
///
|
||||||
|
/// Operand is a zero-page address. Add X to it, then fetch the 16-bit address from that location.
|
||||||
|
/// Example: If X = 0x04 and operand = $20, `LDA ($20,X)` reads from the address at $24/$25.
|
||||||
IndirectX,
|
IndirectX,
|
||||||
|
|
||||||
|
/// Indirect Y (Indirect Indexed)
|
||||||
|
///
|
||||||
|
/// Operand is a zero-page address. Fetch the 16-bit address from that location, then add Y.
|
||||||
|
/// Example: If Y = 0x10 and ($20) = $3000, `LDA ($20),Y` reads from $3010.
|
||||||
IndirectY,
|
IndirectY,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
|
use log::trace;
|
||||||
use crate::address_mode::AddressMode;
|
use crate::address_mode::AddressMode;
|
||||||
use crate::address_mode::AddressMode::*;
|
use crate::address_mode::AddressMode::*;
|
||||||
use crate::address_mode::AddressMode::{Absolute, AbsoluteX, AbsoluteY, Accumulator, Immediate, Implied, Indirect, IndirectX, IndirectY, ZeroPage, ZeroPageX};
|
use crate::address_mode::AddressMode::*;
|
||||||
use crate::instruction_table::INSTRUCTION_TABLE;
|
use crate::instruction_table::INSTRUCTION_TABLE;
|
||||||
use crate::op_info::OpInfo;
|
use crate::op_info::OpInfo;
|
||||||
use crate::operand::Operand;
|
use crate::operand::Operand;
|
||||||
use crate::operation::Operation;
|
use crate::operation::Operation;
|
||||||
use crate::operation::Operation::{ADC, AND, ASL, BCC, BCS, BEQ, BIT, BMI, BNE, BPL, BRK, BVC, BVS, CLC, CLD, CLI, CLV, CMP, CPX, CPY, DEC, DEX, DEY, EOR, INC, INX, JMP, JSR, LDA, LDX, LDY, NOP, ORA, PHA, PHP, PLA, PLP, ROL, ROR, RTI, RTS, SBC, SEC, SED, SEI, STA, STX, STY, TAX, TAY, TSX, TXA, TXS, TYA};
|
use crate::operation::Operation::*;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Instruction {
|
pub struct Instruction {
|
||||||
@ -16,32 +17,28 @@ pub struct Instruction {
|
|||||||
|
|
||||||
impl Instruction {
|
impl Instruction {
|
||||||
pub fn opinfo(bytes: &[u8]) -> Option<OpInfo> {
|
pub fn opinfo(bytes: &[u8]) -> Option<OpInfo> {
|
||||||
println!("DECODING : {bytes:?}");
|
trace!("DECODING : {bytes:?}");
|
||||||
let opcode = bytes.get(0).copied()?;
|
let opcode = bytes.get(0).copied()?;
|
||||||
Some(INSTRUCTION_TABLE[opcode as usize])?
|
Some(INSTRUCTION_TABLE[opcode as usize])?
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode(bytes: &[u8]) -> Option<Instruction> {
|
pub fn decode(bytes: &[u8]) -> Option<Instruction> {
|
||||||
let info = Instruction::opinfo(bytes).unwrap();
|
let info = Instruction::opinfo(bytes)?;
|
||||||
|
|
||||||
let operand = match info.length {
|
let operand = match info.length {
|
||||||
2 => Operand::Byte(bytes.get(1).copied()?),
|
2 => Operand::Byte(*bytes.get(1)?),
|
||||||
3 => {
|
3 => Operand::Word(u16::from_le_bytes([*bytes.get(1)?, *bytes.get(2)?])),
|
||||||
let lo = *bytes.get(1)?;
|
_ => Operand::None,
|
||||||
let hi = *bytes.get(2)?;
|
};
|
||||||
Operand::Word(u16::from_le_bytes([lo, hi]))
|
|
||||||
}
|
|
||||||
_ => Operand::None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let return_value = Some(Instruction {
|
let instruction = Instruction {
|
||||||
op: info.operation,
|
op: info.operation,
|
||||||
mode: info.mode,
|
mode: info.mode,
|
||||||
operand,
|
operand,
|
||||||
});
|
};
|
||||||
|
|
||||||
println!("RETURNING: {:?}", return_value);
|
trace!("RETURNING: {:?}", instruction);
|
||||||
|
Some(instruction)
|
||||||
return_value
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +47,7 @@ impl Instruction {
|
|||||||
mod test {
|
mod test {
|
||||||
use crate::address_mode::AddressMode::*;
|
use crate::address_mode::AddressMode::*;
|
||||||
use crate::instruction::Instruction;
|
use crate::instruction::Instruction;
|
||||||
use crate::operation::Operation::{ADC, INY, LSR};
|
use crate::operation::Operation::*;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@ -1,12 +1,45 @@
|
|||||||
|
|
||||||
|
/// Represents the status flags in the 6502 processor's status register (P).
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub enum Mos6502Flag {
|
pub enum Mos6502Flag {
|
||||||
|
/// Carry Flag (C)
|
||||||
|
///
|
||||||
|
/// Set if an arithmetic operation results in a carry out of the most significant bit (for addition),
|
||||||
|
/// or a borrow (for subtraction). Also used for bit shifts and rotates.
|
||||||
Carry,
|
Carry,
|
||||||
|
|
||||||
|
/// Zero Flag (Z)
|
||||||
|
///
|
||||||
|
/// Set if the result of an operation is zero.
|
||||||
Zero,
|
Zero,
|
||||||
|
|
||||||
|
/// Interrupt Disable Flag (I)
|
||||||
|
///
|
||||||
|
/// When set, disables maskable interrupts (IRQ).
|
||||||
Interrupt,
|
Interrupt,
|
||||||
|
|
||||||
|
/// Decimal Mode Flag (D)
|
||||||
|
///
|
||||||
|
/// When set, arithmetic operations use Binary-Coded Decimal (BCD) mode.
|
||||||
|
/// Note: Not supported on all 6502 variants (e.g., not on the NES CPU).
|
||||||
Decimal,
|
Decimal,
|
||||||
|
|
||||||
|
/// Break Command Flag (B)
|
||||||
|
///
|
||||||
|
/// Set when a BRK (break) instruction is executed.
|
||||||
|
/// Used to distinguish software interrupts from hardware ones.
|
||||||
Break,
|
Break,
|
||||||
|
|
||||||
|
/// Overflow Flag (V)
|
||||||
|
///
|
||||||
|
/// Set when an arithmetic operation results in a signed overflow.
|
||||||
|
/// For example, adding two positive numbers results in a negative.
|
||||||
Overflow,
|
Overflow,
|
||||||
Negative
|
|
||||||
|
/// Negative Flag (N)
|
||||||
|
///
|
||||||
|
/// Set if the result of an operation has bit 7 set (i.e., the result is negative in two's complement).
|
||||||
|
Negative,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|||||||
@ -3,8 +3,12 @@ use crate::operation::Operation;
|
|||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct OpInfo {
|
pub struct OpInfo {
|
||||||
|
/// What is the operation
|
||||||
pub operation: Operation,
|
pub operation: Operation,
|
||||||
|
/// How does this operation access memory
|
||||||
pub mode: AddressMode,
|
pub mode: AddressMode,
|
||||||
|
/// Bytes to represent the instruction and parameters
|
||||||
pub length: u8,
|
pub length: u8,
|
||||||
|
/// CPU Cycles to complete the instruction
|
||||||
pub cycles: u8,
|
pub cycles: u8,
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user