applies chatgpt suggestions.

...
does not appear to decode everything
This commit is contained in:
2025-06-25 09:34:19 -04:00
parent 1b2fb2c221
commit 57544589b3
23 changed files with 1341 additions and 1472 deletions
+1 -2
View File
@@ -1,11 +1,10 @@
use core::instruction::Instruction;
use core::address_mode::AddressMode;
use core::isa::decoder::Decoder;
fn main() {
println!("Taxation is Theft");
Decoder::decode(vec![0b11100011]);
Instruction::from_bytes(vec![0b11100011]);
let instruction = Instruction::ADC(AddressMode::Immediate(0x45));
println!("Instruction = {:?}", instruction.to_string());
+1 -1
View File
@@ -3,4 +3,4 @@ name = "core"
version = "0.1.0"
edition = "2024"
[dependencies]
log = "0.4.26"
log = "0.4"
+16 -10
View File
@@ -1,17 +1,23 @@
use std::fmt::{Display, Formatter};
use std::ops::Add;
use crate::address_mode::Operation::*;
use crate::constants::constants_isa_op::*;
use crate::constants::constants_isa_stub::*;
use crate::mos6502cpu::Mos6502Cpu;
use crate::operation::Operation;
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Debug, Copy, Clone)]
pub enum AddressMode {
Implied,
Accumulator,
Immediate(u8),
ZeroPage(u8),
ZeroPageX(u8),
ZeroPageY(u8),
Absolute(u16),
AbsoluteX(u16),
AbsoluteY(u16),
IndirectX(u8),
IndirectY(u8),
Immediate,
ZeroPage,
ZeroPageX,
ZeroPageY,
Absolute,
AbsoluteX,
AbsoluteY,
Indirect,
IndirectX,
IndirectY,
}
+2 -1
View File
@@ -57,6 +57,7 @@ pub const ISA_OP_CMP_ZP: u8 = 0xc5;
pub const ISA_OP_CMP_ZPX: u8 = 0xd5;
pub const ISA_OP_CMP_ABS: u8 = 0xcd;
pub const ISA_OP_CMP_ABSX: u8 = 0xdd;
pub const ISA_OP_CMP_ABSY: u8 = 0xd9;
pub const ISA_OP_CMP_INDX: u8 = 0xc1;
pub const ISA_OP_CMP_INDY: u8 = 0xd1;
pub const ISA_OP_CPX_I: u8 = 0xe0;
@@ -156,7 +157,7 @@ pub const ISA_OP_STA_ABSY: u8 = 0x99;
pub const ISA_OP_STA_INDX: u8 = 0x81;
pub const ISA_OP_STA_INDY: u8 = 0x91;
pub const ISA_OP_STX_ZP: u8 = 0x86;
pub const ISA_OP_STX_ZPX: u8 = 0x96;
pub const ISA_OP_STX_ZPY: u8 = 0x96;
pub const ISA_OP_STX_ABS: u8 = 0x8e;
pub const ISA_OP_STY_ZP: u8 = 0x84;
pub const ISA_OP_STY_ZPX: u8 = 0x94;
+242
View File
@@ -0,0 +1,242 @@
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::instruction_table::INSTRUCTION_TABLE;
use crate::operand::Operand;
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};
#[derive(Debug, PartialEq)]
pub struct Instruction {
pub op: Operation,
pub mode: AddressMode,
pub operand: Operand,
}
impl Instruction {
pub fn decode(bytes: &[u8]) -> Option<Instruction> {
let opcode = bytes.get(0).copied()?;
let info = INSTRUCTION_TABLE[opcode as usize]?;
let operand = match info.length {
2 => Operand::Byte(bytes.get(1).copied()?),
3 => {
let lo = *bytes.get(1)?;
let hi = *bytes.get(2)?;
Operand::Word(u16::from_le_bytes([lo, hi]))
}
_ => return None,
};
Some(Instruction {
op: info.operation,
mode: info.mode,
operand,
})
}
}
#[cfg(test)]
mod test {
use crate::address_mode::AddressMode::*;
use crate::instruction::Instruction;
use crate::operation::Operation::ADC;
use super::*;
#[test]
fn decode_instruction() {
let params = vec![
// ADC
(vec![0x69, 0xab], Instruction { op: ADC, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0x65, 0xab], Instruction { op: ADC, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0x75, 0xab], Instruction { op: ADC, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0x6d, 0xcd, 0xab], Instruction { op: ADC, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0x7d, 0xcd, 0xab], Instruction { op: ADC, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
(vec![0x79, 0xcd, 0xab], Instruction { op: ADC, mode: AbsoluteY, operand: Operand::Word(0xabcd) }),
(vec![0x61, 0xab], Instruction { op: ADC, mode: IndirectX, operand: Operand::Byte(0xab) }),
(vec![0x71, 0xab], Instruction { op: ADC, mode: IndirectY, operand: Operand::Byte(0xab) }),
// AND
(vec![0x29, 0xab], Instruction { op: AND, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0x25, 0xab], Instruction { op: AND, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0x35, 0xab], Instruction { op: AND, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0x2d, 0xcd, 0xab], Instruction { op: AND, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0x3d, 0xcd, 0xab], Instruction { op: AND, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
(vec![0x39, 0xcd, 0xab], Instruction { op: AND, mode: AbsoluteY, operand: Operand::Word(0xabcd) }),
(vec![0x21, 0xab], Instruction { op: AND, mode: IndirectX, operand: Operand::Byte(0xab) }),
(vec![0x31, 0xab], Instruction { op: AND, mode: IndirectY, operand: Operand::Byte(0xab) }),
// ASL
(vec![0x0a], Instruction { op: ASL, mode: Accumulator, operand: Operand::None }),
(vec![0x06, 0xab], Instruction { op: ASL, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0x16, 0xab], Instruction { op: ASL, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0x0e, 0xcd, 0xab], Instruction { op: ASL, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0x1e, 0xcd, 0xab], Instruction { op: ASL, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
// BIT
(vec![0x24, 0xab], Instruction { op: BIT, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0x2c, 0xcd, 0xab], Instruction { op: BIT, mode: Absolute, operand: Operand::Word(0xabcd) }),
// BCC, BCS, BEQ, BMI, BNE, BPL, BVC, BVS
(vec![0x10, 0xab], Instruction { op: BPL, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0x30, 0xab], Instruction { op: BMI, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0x50, 0xab], Instruction { op: BVC, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0x70, 0xab], Instruction { op: BVS, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0x90, 0xab], Instruction { op: BCC, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0xb0, 0xab], Instruction { op: BCS, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0xd0, 0xab], Instruction { op: BNE, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0xf0, 0xab], Instruction { op: BEQ, mode: Immediate, operand: Operand::Byte(0xab) }),
// BRK
(vec![0x00], Instruction { op: BRK, mode: Implied, operand: Operand::None }),
// CLC, CLD, CLI, CLV
(vec![0x18], Instruction { op: CLC, mode: Implied, operand: Operand::None }),
(vec![0xd8], Instruction { op: CLD, mode: Implied, operand: Operand::None }),
(vec![0x58], Instruction { op: CLI, mode: Implied, operand: Operand::None }),
(vec![0xb8], Instruction { op: CLV, mode: Implied, operand: Operand::None }),
// CMP
(vec![0xc9, 0xab], Instruction { op: CMP, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0xc5, 0xab], Instruction { op: CMP, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0xd5, 0xab], Instruction { op: CMP, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0xcd, 0xcd, 0xab], Instruction { op: CMP, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0xdd, 0xcd, 0xab], Instruction { op: CMP, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
(vec![0xd9, 0xcd, 0xab], Instruction { op: CMP, mode: AbsoluteY, operand: Operand::Word(0xabcd) }),
(vec![0xc1, 0xab], Instruction { op: CMP, mode: IndirectX, operand: Operand::Byte(0xab) }),
(vec![0xd1, 0xab], Instruction { op: CMP, mode: IndirectY, operand: Operand::Byte(0xab) }),
// CPX
(vec![0xe0, 0xab], Instruction { op: CPX, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0xe4, 0xab], Instruction { op: CPX, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0xec, 0xcd, 0xab], Instruction { op: CPX, mode: Absolute, operand: Operand::Word(0xabcd) }),
// CPY
(vec![0xc0, 0xab], Instruction { op: CPY, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0xc4, 0xab], Instruction { op: CPY, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0xcc, 0xcd, 0xab], Instruction { op: CPY, mode: Absolute, operand: Operand::Word(0xabcd) }),
// DEC, DEX, DEY
(vec![0xc6, 0xab], Instruction { op: DEC, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0xd6, 0xab], Instruction { op: DEC, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0xce, 0xcd, 0xab], Instruction { op: DEC, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0xde, 0xcd, 0xab], Instruction { op: DEC, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
(vec![0xca], Instruction { op: DEX, mode: Implied, operand: Operand::None }),
(vec![0x88], Instruction { op: DEY, mode: Implied, operand: Operand::None }),
// EOR
(vec![0x49, 0xab], Instruction { op: EOR, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0x45, 0xab], Instruction { op: EOR, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0x55, 0xab], Instruction { op: EOR, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0x4d, 0xcd, 0xab], Instruction { op: EOR, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0x5d, 0xcd, 0xab], Instruction { op: EOR, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
(vec![0x59, 0xcd, 0xab], Instruction { op: EOR, mode: AbsoluteY, operand: Operand::Word(0xabcd) }),
(vec![0x41, 0xab], Instruction { op: EOR, mode: IndirectX, operand: Operand::Byte(0xab) }),
(vec![0x51, 0xab], Instruction { op: EOR, mode: IndirectY, operand: Operand::Byte(0xab) }),
// INC, INX, INY
(vec![0xe6, 0xab], Instruction { op: INC, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0xf6, 0xab], Instruction { op: INC, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0xee, 0xcd, 0xab], Instruction { op: INC, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0xfe, 0xcd, 0xab], Instruction { op: INC, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
(vec![0xe8], Instruction { op: INX, mode: Implied, operand: Operand::None }),
(vec![0xc8], Instruction { op: INX, mode: Implied, operand: Operand::None }),
// JMP, JSR
(vec![0x4c, 0xcd, 0xab], Instruction { op: JMP, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0x6c, 0xcd, 0xab], Instruction { op: JMP, mode: Indirect, operand: Operand::Word(0xabcd) }),
(vec![0x20], Instruction { op: JSR, mode: Implied, operand: Operand::None }),
// LDA
(vec![0xa9, 0xab], Instruction { op: LDA, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0xa5, 0xab], Instruction { op: LDA, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0xb5, 0xab], Instruction { op: LDA, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0xad, 0xcd, 0xab], Instruction { op: LDA, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0xbd, 0xcd, 0xab], Instruction { op: LDA, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
(vec![0xb9, 0xcd, 0xab], Instruction { op: LDA, mode: AbsoluteY, operand: Operand::Word(0xabcd) }),
(vec![0xa1, 0xab], Instruction { op: LDA, mode: IndirectX, operand: Operand::Byte(0xab) }),
(vec![0xb1, 0xab], Instruction { op: LDA, mode: IndirectY, operand: Operand::Byte(0xab) }),
// LDX
(vec![0xa2, 0xab], Instruction { op: LDX, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0xa6, 0xab], Instruction { op: LDX, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0xb6, 0xab], Instruction { op: LDX, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0xae, 0xcd, 0xab], Instruction { op: LDX, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0xbe, 0xcd, 0xab], Instruction { op: LDX, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
// LDY
(vec![0xa2, 0xab], Instruction { op: LDY, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0xa6, 0xab], Instruction { op: LDY, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0xb6, 0xab], Instruction { op: LDY, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0xae, 0xcd, 0xab], Instruction { op: LDY, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0xbe, 0xcd, 0xab], Instruction { op: LDY, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
// LSR
(vec![0x4a, 0xab], Instruction { op: LDY, mode: Accumulator, operand: Operand::Byte(0xab) }),
(vec![0x46, 0xab], Instruction { op: LDY, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0x56, 0xab], Instruction { op: LDY, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0x4e, 0xcd, 0xab], Instruction { op: LDY, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0x5e, 0xcd, 0xab], Instruction { op: LDY, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
// NOP
(vec![0xea], Instruction { op: NOP, mode: Implied, operand: Operand::None }),
// ORA
(vec![0x09, 0xab], Instruction { op: ORA, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0x05, 0xab], Instruction { op: ORA, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0x15, 0xab], Instruction { op: ORA, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0x0d, 0xcd, 0xab], Instruction { op: ORA, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0x1d, 0xcd, 0xab], Instruction { op: ORA, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
(vec![0x19, 0xcd, 0xab], Instruction { op: ORA, mode: AbsoluteY, operand: Operand::Word(0xabcd) }),
(vec![0x01, 0xab], Instruction { op: ORA, mode: IndirectX, operand: Operand::Byte(0xab) }),
(vec![0x11, 0xab], Instruction { op: ORA, mode: IndirectY, operand: Operand::Byte(0xab) }),
// PHA, PHP, PLA, PLP
(vec![0x48], Instruction { op: PHA, mode: Implied, operand: Operand::None }),
(vec![0x08], Instruction { op: PHP, mode: Implied, operand: Operand::None }),
(vec![0x68], Instruction { op: PLA, mode: Implied, operand: Operand::None }),
(vec![0x28], Instruction { op: PLP, mode: Implied, operand: Operand::None }),
// ROL
(vec![0x2a, 0xab], Instruction { op: ROL, mode: Accumulator, operand: Operand::Byte(0xab) }),
(vec![0x26, 0xab], Instruction { op: ROL, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0x36, 0xab], Instruction { op: ROL, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0x2e, 0xcd, 0xab], Instruction { op: ROL, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0x3e, 0xcd, 0xab], Instruction { op: ROL, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
// ROR
(vec![0x6a, 0xab], Instruction { op: ROR, mode: Accumulator, operand: Operand::Byte(0xab) }),
(vec![0x66, 0xab], Instruction { op: ROR, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0x76, 0xab], Instruction { op: ROR, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0x6e, 0xcd, 0xab], Instruction { op: ROR, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0x7e, 0xcd, 0xab], Instruction { op: ROR, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
// RTI, RTS
(vec![0x40], Instruction { op: RTI, mode: Implied, operand: Operand::None }),
(vec![0x60], Instruction { op: RTS, mode: Implied, operand: Operand::None }),
// SBC
(vec![0xe9, 0xab], Instruction { op: SBC, mode: Immediate, operand: Operand::Byte(0xab) }),
(vec![0xe5, 0xab], Instruction { op: SBC, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0xf5, 0xab], Instruction { op: SBC, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0xed, 0xcd, 0xab], Instruction { op: SBC, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0xfd, 0xcd, 0xab], Instruction { op: SBC, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
(vec![0xf9, 0xcd, 0xab], Instruction { op: SBC, mode: AbsoluteY, operand: Operand::Word(0xabcd) }),
(vec![0xe1, 0xab], Instruction { op: SBC, mode: IndirectX, operand: Operand::Byte(0xab) }),
(vec![0xf1, 0xab], Instruction { op: SBC, mode: IndirectY, operand: Operand::Byte(0xab) }),
// SEC, SED, SEI
(vec![0x38], Instruction { op: SEC, mode: Implied, operand: Operand::None }),
(vec![0xf8], Instruction { op: SED, mode: Implied, operand: Operand::None }),
(vec![0x78], Instruction { op: SEI, mode: Implied, operand: Operand::None }),
// STA
(vec![0x85, 0xab], Instruction { op: STA, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0x95, 0xab], Instruction { op: STA, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0x8d, 0xcd, 0xab], Instruction { op: STA, mode: Absolute, operand: Operand::Word(0xabcd) }),
(vec![0x9d, 0xcd, 0xab], Instruction { op: STA, mode: AbsoluteX, operand: Operand::Word(0xabcd) }),
(vec![0x99, 0xcd, 0xab], Instruction { op: STA, mode: AbsoluteY, operand: Operand::Word(0xabcd) }),
(vec![0x81, 0xab], Instruction { op: STA, mode: IndirectX, operand: Operand::Byte(0xab) }),
(vec![0x91, 0xab], Instruction { op: STA, mode: IndirectY, operand: Operand::Byte(0xab) }),
// STX
(vec![0x86, 0xab], Instruction { op: STX, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0x96, 0xab], Instruction { op: STX, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0x8e, 0xcd, 0xab], Instruction { op: STX, mode: Absolute, operand: Operand::Word(0xabcd) }),
// STY
(vec![0x84, 0xab], Instruction { op: STY, mode: ZeroPage, operand: Operand::Byte(0xab) }),
(vec![0x94, 0xab], Instruction { op: STY, mode: ZeroPageX, operand: Operand::Byte(0xab) }),
(vec![0x8c, 0xcd, 0xab], Instruction { op: STY, mode: Absolute, operand: Operand::Word(0xabcd) }),
// TAX, TAY, TSX, TXA, TXS, TYA
(vec![0xaa], Instruction { op: TAX, mode: Implied, operand: Operand::None }),
(vec![0xa8], Instruction { op: TAY, mode: Implied, operand: Operand::None }),
(vec![0xba], Instruction { op: TSX, mode: Implied, operand: Operand::None }),
(vec![0x8a], Instruction { op: TXA, mode: Implied, operand: Operand::None }),
(vec![0x9a], Instruction { op: TXS, mode: Implied, operand: Operand::None }),
(vec![0x98], Instruction { op: TYA, mode: Implied, operand: Operand::None })
];
for (bytes, instruction) in params {
let result = Instruction::decode(&bytes);
if let Some(instruction) = result {
assert_eq!(Instruction::decode(&bytes).unwrap(), instruction)
} else {
println!("Failed to decode {:?}", bytes);
}
}
}
}
-285
View File
@@ -1,285 +0,0 @@
use log::debug;
use crate::address_mode::AddressMode;
use crate::instruction::Instruction;
use crate::mos6502cpu::Mos6502Cpu;
use crate::mos6502flags::Mos6502Flag::{Carry, Decimal, Interrupt, Overflow};
impl Instruction {
fn execute(&self, mut system: Mos6502Cpu) {
match self {
// ADC Add with Carry
// A,Z,C,N = A+M+C
//
// This instruction adds the contents of a memory location to the accumulator together with the carry bit. If overflow occurs the carry bit is set, this enables multiple byte addition to be performed.
//
// Processor Status after use:
//
// C Carry Flag Set if overflow in bit 7
// Z Zero Flag Set if A = 0
// I Interrupt Disable Not affected
// D Decimal Mode Flag Not affected
// B Break Command Not affected
// V Overflow Flag Set if sign bit is incorrect
// N Negative Flag Set if bit 7 set
Instruction::ADC(mode) => {
match mode {
AddressMode::Immediate(_) => {}
AddressMode::ZeroPage(_) => {}
AddressMode::ZeroPageX(_) => {}
AddressMode::Absolute(_) => {}
AddressMode::AbsoluteX(_) => {}
AddressMode::AbsoluteY(_) => {}
AddressMode::IndirectX(_) => {}
AddressMode::IndirectY(_) => {}
_ => {}
}
}
Instruction::AND(address) => {
match address {
AddressMode::Immediate(_) => {}
AddressMode::ZeroPage(_) => {}
AddressMode::ZeroPageX(_) => {}
AddressMode::Absolute(_) => {}
AddressMode::AbsoluteX(_) => {}
AddressMode::AbsoluteY(_) => {}
AddressMode::IndirectX(_) => {}
AddressMode::IndirectY(_) => {}
_ => {
// NOOP
}
}
}
Instruction::ASL(mode) => {
match mode {
// ISA_OP_ASL_A
AddressMode::Accumulator => {}
AddressMode::ZeroPage(_) => {}
AddressMode::ZeroPageX(_) => {}
AddressMode::Absolute(_) => {}
AddressMode::AbsoluteX(_) => {}
_ => {}
}
}
Instruction::BCC(mode) => {
match mode {
AddressMode::Immediate(value) => {}
_ => {}
}
}
Instruction::BCS(mode) => {
match mode {
AddressMode::Immediate(value) => {}
_ => {}
}
}
Instruction::BEQ(mode) => {
match mode {
AddressMode::Immediate(value) => {}
_ => {}
}
}
Instruction::BIT(mode) => {
match mode {
AddressMode::ZeroPage(value) => {}
AddressMode::Absolute(value) => {}
_ => {}
}
}
Instruction::BMI(mode) => {
match mode {
AddressMode::Immediate(value) => {}
_ => {}
}
}
Instruction::BNE(mode) => {
match mode {
AddressMode::Immediate(value) => {}
_ => {}
}
}
Instruction::BPL(mode) => {
match mode {
AddressMode::Immediate(value) => {}
_ => {}
}
}
Instruction::BRK => {}
Instruction::BVC(mode) => {
match mode {
AddressMode::Immediate(value) => {}
_ => {}
}
}
Instruction::BVS(mode) => {
match mode {
AddressMode::Immediate(value) => {}
_ => {}
}
}
Instruction::CLC => {
system.poke_flag(Carry, false)
}
Instruction::CLD => {
system.poke_flag(Decimal, false)
}
Instruction::CLI => {
system.poke_flag(Interrupt, false)
}
Instruction::CLV => {
system.poke_flag(Overflow, false)
}
Instruction::CMP(mode) => {
match mode {
AddressMode::Immediate(_) => {}
AddressMode::ZeroPage(_) => {}
AddressMode::ZeroPageX(_) => {}
AddressMode::Absolute(_) => {}
AddressMode::AbsoluteX(_) => {}
AddressMode::AbsoluteY(_) => {}
AddressMode::IndirectX(_) => {}
AddressMode::IndirectY(_) => {}
_ => {}
}
}
Instruction::CPX(mode) => {
match mode {
AddressMode::Immediate(_) => {}
AddressMode::ZeroPage(_) => {}
AddressMode::ZeroPageX(_) => {}
AddressMode::Absolute(_) => {}
AddressMode::AbsoluteX(_) => {}
AddressMode::AbsoluteY(_) => {}
AddressMode::IndirectX(_) => {}
AddressMode::IndirectY(_) => {}
_ => {}
}
}
Instruction::CPY(mode) => {
match mode {
AddressMode::Immediate(_) => {}
AddressMode::ZeroPage(_) => {}
AddressMode::ZeroPageX(_) => {}
AddressMode::Absolute(_) => {}
AddressMode::AbsoluteX(_) => {}
AddressMode::AbsoluteY(_) => {}
AddressMode::IndirectX(_) => {}
AddressMode::IndirectY(_) => {}
_ => {}
}
}
Instruction::DEC(mode) => {
match mode {
AddressMode::ZeroPage(_) => {}
AddressMode::ZeroPageX(_) => {}
AddressMode::Absolute(_) => {}
AddressMode::AbsoluteX(_) => {}
_ => {}
}
}
Instruction::DEX => {
let mut x = system.peek_x();
x -= 1;
system.poke_x(x);
}
Instruction::DEY => {
let mut y = system.peek_y();
y -= 1;
system.poke_y(y);
}
Instruction::EOR(mode) => {
match mode {
AddressMode::Immediate(_) => {}
AddressMode::ZeroPage(_) => {}
AddressMode::ZeroPageX(_) => {}
AddressMode::Absolute(_) => {}
AddressMode::AbsoluteX(_) => {}
AddressMode::AbsoluteY(_) => {}
AddressMode::IndirectX(_) => {}
AddressMode::IndirectY(_) => {}
_ => {}
}
}
Instruction::INC(mode) => {
match mode {
AddressMode::ZeroPage(value) => {}
AddressMode::ZeroPageX(value) => {}
AddressMode::Absolute(value) => {}
AddressMode::AbsoluteX(value) => {}
_ => {}
}
}
Instruction::INX => {
let mut x = system.peek_x();
x += 1;
system.poke_x(x);
}
Instruction::INY => {
let mut y = system.peek_y();
y += 1;
system.poke_y(y);
}
Instruction::JMP(mode) => {
match mode {
AddressMode::Absolute(_) => {}
AddressMode::IndirectX(_) => {}
_ => {}
}
}
Instruction::JSR(mode) => {
match mode {
AddressMode::Absolute(address) => {}
_ => {}
}
}
Instruction::LDA(mode) => {
match mode {
AddressMode::Immediate(value) => {
system.poke_a(*value)
}
AddressMode::ZeroPage(offset) => {
let value_to_write = system.peek(*offset as u16);
system.poke_a(value_to_write);
}
AddressMode::ZeroPageX(_) => {
let current_x = system.peek_x();
}
AddressMode::Absolute(_) => {}
AddressMode::AbsoluteX(_) => {}
AddressMode::AbsoluteY(_) => {}
AddressMode::IndirectX(_) => {}
AddressMode::IndirectY(_) => {}
_ => {
debug!("Invalid LDA instruction");
}
};
}
Instruction::LDX(_) => {}
Instruction::LDY(_) => {}
Instruction::LSR(_) => {}
Instruction::NOP => {}
Instruction::ORA(_) => {}
Instruction::PHA => {}
Instruction::PHP => {}
Instruction::PLA => {}
Instruction::PLP => {}
Instruction::ROL(_) => {}
Instruction::ROR(_) => {}
Instruction::RTI => {}
Instruction::RTS => {}
Instruction::SBC(_) => {}
Instruction::SEC => {}
Instruction::SED => {}
Instruction::SEI => {}
Instruction::STA(_) => {}
Instruction::STX(_) => {}
Instruction::STY(_) => {}
Instruction::TAX => {}
Instruction::TAY => {}
Instruction::TSX => {}
Instruction::TXA => {}
Instruction::TXS => {}
Instruction::TYA => {}
};
}
}
-183
View File
@@ -1,183 +0,0 @@
use crate::address_mode::AddressMode::*;
use crate::constants::constants_isa_op::*;
use crate::instruction::Instruction;
use crate::instruction::Instruction::*;
fn join_word(low: u8, high: u8) -> u16 {
((high as u16) << 8) | low as u16
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_join_word() {
let low: u8 = 0xcd;
let high: u8 = 0xab;
assert_eq!(
join_word(low, high),
0xabcd
);
}
}
impl Instruction {
pub fn from_bytes(decode_from: Vec<u8>) -> Instruction {
let id_byte = decode_from[0];
match id_byte {
ISA_OP_ADC_I..=ISA_OP_ADC_I => ADC(Immediate(decode_from[1])),
ISA_OP_ADC_Z..=ISA_OP_ADC_Z => ADC(ZeroPage(decode_from[1])),
ISA_OP_ADC_ZX..=ISA_OP_ADC_ZX => ADC(ZeroPageX(decode_from[1])),
ISA_OP_ADC_ABS..=ISA_OP_ADC_ABS => ADC(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_ADC_ABSX..=ISA_OP_ADC_ABSX => ADC(AbsoluteX(join_word(decode_from[1], decode_from[2]))),
ISA_OP_ADC_ABSY..=ISA_OP_ADC_ABSY => ADC(AbsoluteY(join_word(decode_from[1], decode_from[2]))),
ISA_OP_ADC_INDX..=ISA_OP_ADC_INDX => ADC(IndirectX(decode_from[1])),
ISA_OP_ADC_INDY..=ISA_OP_ADC_INDY => ADC(IndirectY(decode_from[1])),
ISA_OP_AND_I..=ISA_OP_AND_I => AND(Immediate(decode_from[1])),
ISA_OP_AND_Z..=ISA_OP_AND_Z => AND(ZeroPage(decode_from[1])),
ISA_OP_AND_ZX..=ISA_OP_AND_ZX => AND(ZeroPageX(decode_from[1])),
ISA_OP_AND_ABS..=ISA_OP_AND_ABS => AND(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_AND_ABSX..=ISA_OP_AND_ABSX => AND(AbsoluteX(join_word(decode_from[1], decode_from[2]))),
ISA_OP_AND_ABSY..=ISA_OP_AND_ABSY => AND(AbsoluteY(join_word(decode_from[1], decode_from[2]))),
ISA_OP_AND_INDX..=ISA_OP_AND_INDX => AND(IndirectX(decode_from[1])),
ISA_OP_AND_INDY..=ISA_OP_AND_INDY => AND(IndirectY(decode_from[1])),
ISA_OP_ASL_A..=ISA_OP_ASL_A => ASL(Accumulator),
ISA_OP_ASL_Z..=ISA_OP_ASL_Z => ASL(ZeroPage(decode_from[1])),
ISA_OP_ASL_ZX..=ISA_OP_ASL_ZX => ASL(ZeroPageX(decode_from[1])),
ISA_OP_ASL_ABS..=ISA_OP_ASL_ABS => ASL(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_ASL_ABSX..=ISA_OP_ASL_ABSX => ASL(AbsoluteX(join_word(decode_from[1], decode_from[2]))),
ISA_OP_BCC..=ISA_OP_BCC => BCC(Immediate(decode_from[1])),
ISA_OP_BCS..=ISA_OP_BCS => BCS(Immediate(decode_from[1])),
ISA_OP_BEQ..=ISA_OP_BEQ => BEQ(Immediate(decode_from[1])),
ISA_OP_BIT_ZP..=ISA_OP_BIT_ZP => BIT(ZeroPage(decode_from[1])),
ISA_OP_BIT_ABS..=ISA_OP_BIT_ABS => BIT(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_BMI..=ISA_OP_BMI => BMI(Immediate(decode_from[1])),
ISA_OP_BNE..=ISA_OP_BNE => BNE(Immediate(decode_from[1])),
ISA_OP_BPL..=ISA_OP_BPL => BPL(Immediate(decode_from[1])),
ISA_OP_BRK..=ISA_OP_BRK => BRK,
ISA_OP_BVC..=ISA_OP_BVC => BVC(Immediate(decode_from[1])),
ISA_OP_BVS..=ISA_OP_BVS => BVS(Immediate(decode_from[1])),
ISA_OP_CLC..=ISA_OP_CLC => CLC,
ISA_OP_CLD..=ISA_OP_CLD => CLD,
ISA_OP_CLI..=ISA_OP_CLI => CLI,
ISA_OP_CLV..=ISA_OP_CLV => CLV,
ISA_OP_CMP_I..=ISA_OP_CMP_I => CMP(Immediate(decode_from[1])),
ISA_OP_CMP_ZP..=ISA_OP_CMP_ZP => CMP(ZeroPage(decode_from[1])),
ISA_OP_CMP_ZPX..=ISA_OP_CMP_ZPX => CMP(ZeroPageX(decode_from[1])),
ISA_OP_CMP_ABS..=ISA_OP_CMP_ABS => CMP(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_CMP_ABSX..=ISA_OP_CMP_ABSX => CMP(AbsoluteX(join_word(decode_from[1], decode_from[2]))),
ISA_OP_CMP_INDX..=ISA_OP_CMP_INDX => CMP(IndirectX(decode_from[1])),
ISA_OP_CMP_INDY..=ISA_OP_CMP_INDY => CMP(IndirectY(decode_from[1])),
ISA_OP_CPX_I..=ISA_OP_CPX_I => CPX(Immediate(decode_from[1])),
ISA_OP_CPX_ZP..=ISA_OP_CPX_ZP => CPX(ZeroPage(decode_from[1])),
ISA_OP_CPX_ABS..=ISA_OP_CPX_ABS => CPX(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_CPY_I..=ISA_OP_CPY_I => CPY(Immediate(decode_from[1])),
ISA_OP_CPY_ZP..=ISA_OP_CPY_ZP => CPY(ZeroPage(decode_from[1])),
ISA_OP_CPY_ABS..=ISA_OP_CPY_ABS => CPY(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_DEC_ZP..=ISA_OP_DEC_ZP => DEC(ZeroPage(decode_from[1])),
ISA_OP_DEC_ZPX..=ISA_OP_DEC_ZPX => DEC(ZeroPageX(decode_from[1])),
ISA_OP_DEC_ABS..=ISA_OP_DEC_ABS => DEC(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_DEC_ABSX..=ISA_OP_DEC_ABSX => DEC(AbsoluteX(join_word(decode_from[1], decode_from[1]))),
ISA_OP_DEX..=ISA_OP_DEX => DEX,
ISA_OP_DEY..=ISA_OP_DEY => DEY,
ISA_OP_EOR_I..=ISA_OP_EOR_I => EOR(Immediate(decode_from[1])),
ISA_OP_EOR_ZP..=ISA_OP_EOR_ZP => EOR(ZeroPage(decode_from[1])),
ISA_OP_EOR_ZPX..=ISA_OP_EOR_ZPX => EOR(ZeroPageX(decode_from[1])),
ISA_OP_EOR_ABS..=ISA_OP_EOR_ABS => EOR(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_EOR_ABSX..=ISA_OP_EOR_ABSX => EOR(AbsoluteX(join_word(decode_from[1], decode_from[2]))),
ISA_OP_EOR_ABSY..=ISA_OP_EOR_ABSY => EOR(AbsoluteY(join_word(decode_from[1], decode_from[2]))),
ISA_OP_EOR_INDX..=ISA_OP_EOR_INDX => EOR(IndirectX(decode_from[1])),
ISA_OP_EOR_INDY..=ISA_OP_EOR_INDY => EOR(IndirectY(decode_from[1])),
ISA_OP_INC_ZP..=ISA_OP_INC_ZP => INC(ZeroPage(decode_from[1])),
ISA_OP_INC_ZPX..=ISA_OP_INC_ZPX => INC(ZeroPageX(decode_from[1])),
ISA_OP_INC_ABS..=ISA_OP_INC_ABS => INC(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_INC_ABSX..=ISA_OP_INC_ABSX => INC(AbsoluteX(join_word(decode_from[1], decode_from[2]))),
ISA_OP_INX..=ISA_OP_INX => INX,
ISA_OP_INY..=ISA_OP_INY => INY,
ISA_OP_JMP_ABS..=ISA_OP_JMP_ABS => JMP(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_JMP_IND..=ISA_OP_JMP_IND => JMP(IndirectX(decode_from[1])),
ISA_OP_JSR..=ISA_OP_JSR => JSR(Immediate(decode_from[1])),
ISA_OP_LDA_I..=ISA_OP_LDA_I => LDA(Immediate(decode_from[1])),
ISA_OP_LDA_Z..=ISA_OP_LDA_Z => LDA(ZeroPage(decode_from[1])),
ISA_OP_LDA_ZX..=ISA_OP_LDA_ZX => LDA(ZeroPageX(decode_from[1])),
ISA_OP_LDA_ABS..=ISA_OP_LDA_ABS => LDA(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_LDA_ABSX..=ISA_OP_LDA_ABSX => LDA(AbsoluteX(join_word(decode_from[1], decode_from[2]))),
ISA_OP_LDA_ABSY..=ISA_OP_LDA_ABSY => LDA(AbsoluteY(join_word(decode_from[1], decode_from[2]))),
ISA_OP_LDA_INDX..=ISA_OP_LDA_INDX => LDA(IndirectX(decode_from[1])),
ISA_OP_LDA_INDY..=ISA_OP_LDA_INDY => LDA(IndirectY(decode_from[1])),
ISA_OP_LDX_I..=ISA_OP_LDX_I => LDX(Immediate(decode_from[1])),
ISA_OP_LDX_ZP..=ISA_OP_LDX_ZP => LDX(ZeroPage(decode_from[1])),
ISA_OP_LDX_ZPY..=ISA_OP_LDX_ZPY => LDX(ZeroPageY(decode_from[1])),
ISA_OP_STX_ZP..=ISA_OP_STX_ZP => STX(ZeroPage(decode_from[1])),
ISA_OP_LDX_ABS..=ISA_OP_LDX_ABS => LDX(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_LDX_ABSY..=ISA_OP_LDX_ABSY => LDX(AbsoluteY(join_word(decode_from[1], decode_from[2]))),
ISA_OP_LDY_I..=ISA_OP_LDY_I => LDY(Immediate(decode_from[1])),
ISA_OP_LDY_ZP..=ISA_OP_LDY_ZP => LDY(ZeroPage(decode_from[1])),
ISA_OP_LDY_ZPX..=ISA_OP_LDY_ZPX => LDY(ZeroPageX(decode_from[1])),
ISA_OP_LDY_ABS..=ISA_OP_LDY_ABS => LDY(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_LDY_ABSX..=ISA_OP_LDY_ABSX => LDY(AbsoluteX(join_word(decode_from[1], decode_from[2]))),
ISA_OP_LSR_A..=ISA_OP_LSR_A => LSR(Accumulator),
ISA_OP_LSR_ZP..=ISA_OP_LSR_ZP => LSR(ZeroPage(decode_from[1])),
ISA_OP_LSR_ZPX..=ISA_OP_LSR_ZPX => LSR(ZeroPageX(decode_from[1])),
ISA_OP_LSR_ABS..=ISA_OP_LSR_ABS => LSR(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_LSR_ABSX..=ISA_OP_LSR_ABSX => LSR(AbsoluteX(join_word(decode_from[1], decode_from[2]))),
ISA_OP_NOP..=ISA_OP_NOP => NOP,
ISA_OP_ORA_I..=ISA_OP_ORA_I => ORA(Immediate(decode_from[1])),
ISA_OP_ORA_ZP..=ISA_OP_ORA_ZP => ORA(ZeroPage(decode_from[1])),
ISA_OP_ORA_ZPX..=ISA_OP_ORA_ZPX => ORA(ZeroPageX(decode_from[1])),
ISA_OP_ORA_ABS..=ISA_OP_ORA_ABS => ORA(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_ORA_ABSX..=ISA_OP_ORA_ABSX => ORA(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_ORA_ABSY..=ISA_OP_ORA_ABSY => ORA(AbsoluteY(join_word(decode_from[1], decode_from[2]))),
ISA_OP_ORA_INDX..=ISA_OP_ORA_INDX => ORA(IndirectX(decode_from[1])),
ISA_OP_ORA_INDY..=ISA_OP_ORA_INDY => ORA(IndirectY(decode_from[1])),
ISA_OP_PHA..=ISA_OP_PHA => PHA,
ISA_OP_PHP..=ISA_OP_PHP => PHP,
ISA_OP_PLA..=ISA_OP_PLA => PLA,
ISA_OP_PLP..=ISA_OP_PLP => PLP,
ISA_OP_ROL_A..=ISA_OP_ROL_A => ROL(Accumulator),
ISA_OP_ROL_ZP..=ISA_OP_ROL_ZP => ROL(ZeroPage(decode_from[1])),
ISA_OP_ROL_ZPX..=ISA_OP_ROL_ZPX => ROL(ZeroPageX(decode_from[1])),
ISA_OP_ROL_ABS..=ISA_OP_ROL_ABS => ROL(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_ROL_ABSX..=ISA_OP_ROL_ABSX => ROL(AbsoluteX(join_word(decode_from[1], decode_from[2]))),
ISA_OP_ROR_A..=ISA_OP_ROR_A => ROR(Accumulator),
ISA_OP_ROR_ZP..=ISA_OP_ROR_ZP => ROR(ZeroPage(decode_from[1])),
ISA_OP_ROR_ZPX..=ISA_OP_ROR_ZPX => ROR(ZeroPageX(decode_from[1])),
ISA_OP_ROR_ABS..=ISA_OP_ROR_ABS => ROR(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_ROR_ABSX..=ISA_OP_ROR_ABSX => ROR(AbsoluteX(join_word(decode_from[1], decode_from[2]))),
ISA_OP_RTI..=ISA_OP_RTI => RTI,
ISA_OP_RTS..=ISA_OP_RTS => RTS,
ISA_OP_SBC_I..=ISA_OP_SBC_I => SBC(Immediate(decode_from[1])),
ISA_OP_SBC_ZP..=ISA_OP_SBC_ZP => SBC(ZeroPage(decode_from[1])),
ISA_OP_SBC_ZPX..=ISA_OP_SBC_ZPX => SBC(ZeroPageX(decode_from[1])),
ISA_OP_SBC_ABS..=ISA_OP_SBC_ABS => SBC(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_SBC_ABSX..=ISA_OP_SBC_ABSX => SBC(AbsoluteX(join_word(decode_from[1], decode_from[2]))),
ISA_OP_SBC_ABSY..=ISA_OP_SBC_ABSY => SBC(AbsoluteY(join_word(decode_from[1], decode_from[2]))),
ISA_OP_SBC_INDX..=ISA_OP_SBC_INDX => SBC(IndirectX(decode_from[1])),
ISA_OP_SBC_INDY..=ISA_OP_SBC_INDY => SBC(IndirectY(decode_from[1])),
ISA_OP_SEC..=ISA_OP_SEC => SEC,
ISA_OP_SED..=ISA_OP_SED => SED,
ISA_OP_SEI..=ISA_OP_SEI => SEI,
// ISA_OP_STA_ZP..=ISA_OP_STA_ZP => STA(ZeroPage(decode_from[1])),
ISA_OP_STA_ZPX..=ISA_OP_STA_ZPX => STA(ZeroPageX(decode_from[1])),
ISA_OP_STA_ABS..=ISA_OP_STA_ABS => STA(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_STA_ABSX..=ISA_OP_STA_ABSX => STA(AbsoluteX(join_word(decode_from[1], decode_from[2]))),
ISA_OP_STA_ABSY..=ISA_OP_STA_ABSY => STA(AbsoluteY(join_word(decode_from[1], decode_from[2]))),
ISA_OP_STA_INDX..=ISA_OP_STA_INDX => STA(IndirectX(decode_from[1])),
ISA_OP_STA_INDY..=ISA_OP_STA_INDY => STA(IndirectY(decode_from[1])),
ISA_OP_STX_ZPX..=ISA_OP_STX_ZPX => STX(ZeroPageX(decode_from[1])),
ISA_OP_STX_ABS..=ISA_OP_STX_ABS => STX(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_STY_ZP..=ISA_OP_STY_ZP => STY(ZeroPage(decode_from[1])),
ISA_OP_STY_ZPX..=ISA_OP_STY_ZPX => STY(ZeroPageX(decode_from[1])),
ISA_OP_STY_ABS..=ISA_OP_STY_ABS => STY(Absolute(join_word(decode_from[1], decode_from[2]))),
ISA_OP_TAX..=ISA_OP_TAX => TAX,
ISA_OP_TAY..=ISA_OP_TAY => TAY,
ISA_OP_TSX..=ISA_OP_TSX => TSX,
ISA_OP_TXA..=ISA_OP_TXA => TXA,
ISA_OP_TXS..=ISA_OP_TXS => TXS,
ISA_OP_TYA..=ISA_OP_TYA => TYA,
_ => NOP
}
}
}
-71
View File
@@ -1,71 +0,0 @@
use crate::instruction::Instruction;
use crate::constants::constants_isa_stub::*;
use crate::instruction::Instruction::*;
impl Instruction {
/// returns the 'stub' of the instruction.
///
/// ex: LDA $4452 -> LDA
/// BCC $43 -> BCC
pub fn stub(&self) -> String {
match self {
ADC(_) => ISA_STUB_ADC,
AND(_) => ISA_STUB_AND,
ASL(_) => ISA_STUB_ASL,
BCC(_) => ISA_STUB_BCC,
BCS(_) => ISA_STUB_BCS,
BEQ(_) => ISA_STUB_BEQ,
BIT(_) => ISA_STUB_BIT,
BMI(_) => ISA_STUB_BMI,
BNE(_) => ISA_STUB_BNE,
BPL(_) => ISA_STUB_BPL,
BRK => ISA_STUB_BRK,
BVC(_) => ISA_STUB_BVC,
BVS(_) => ISA_STUB_BVS,
CLC => ISA_STUB_CLC,
CLD => ISA_STUB_CLD,
CLI => ISA_STUB_CLI,
CLV => ISA_STUB_CLV,
CMP(_) => ISA_STUB_CMP,
CPX(_) => ISA_STUB_CPX,
CPY(_) => ISA_STUB_CPY,
DEC(_) => ISA_STUB_DEC,
DEX => ISA_STUB_DEX,
DEY => ISA_STUB_DEY,
EOR(_) => ISA_STUB_EOR,
INC(_) => ISA_STUB_INC,
INX => ISA_STUB_INX,
INY => ISA_STUB_INY,
JMP(_) => ISA_STUB_JMP,
JSR(_) => ISA_STUB_JSR,
LDA(_) => ISA_STUB_LDA,
LDX(_) => ISA_STUB_LDX,
LDY(_) => ISA_STUB_LDY,
LSR(_) => ISA_STUB_LSR,
NOP => ISA_STUB_NOP,
ORA(_) => ISA_STUB_ORA,
PHA => ISA_STUB_PHA,
PHP => ISA_STUB_PHP,
PLA => ISA_STUB_PLA,
PLP => ISA_STUB_PLP,
ROL(_) => ISA_STUB_ROL,
ROR(_) => ISA_STUB_ROR,
RTI => ISA_STUB_RTI,
RTS => ISA_STUB_RTS,
SBC(_) => ISA_STUB_SBC,
SEC => ISA_STUB_SEC,
SED => ISA_STUB_SED,
SEI => ISA_STUB_SEI,
STA(_) => ISA_STUB_STA,
STX(_) => ISA_STUB_STX,
STY(_) => ISA_STUB_STY,
TAX => ISA_STUB_TAX,
TAY => ISA_STUB_TAY,
TSX => ISA_STUB_TSX,
TXA => ISA_STUB_TXA,
TXS => ISA_STUB_TXS,
TYA => ISA_STUB_TYA
}.to_string()
}
}
-411
View File
@@ -1,411 +0,0 @@
use crate::address_mode::AddressMode;
use crate::address_mode::AddressMode::{Absolute, AbsoluteX, AbsoluteY, Immediate, IndirectX, IndirectY, ZeroPage, ZeroPageX, ZeroPageY};
use crate::constants::constants_isa_op::*;
use crate::instruction::Instruction;
use crate::instruction::Instruction::*;
fn split_word_hl(to_split: u16) -> (u8, u8) {
let low = (to_split & 0xff) as u8;
let high = ((to_split & 0xff00) >> 8) as u8;
(high, low)
}
fn split_word_lh(to_split: u16) -> (u8, u8) {
let low = (to_split & 0xff) as u8;
let high = ((to_split & 0xff00) >> 8) as u8;
(low, high)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn split_le() {
let value = 0xabcd;
let (high, low) = split_word_hl(value);
assert_eq!(low, 0xcd);
assert_eq!(high, 0xab);
}
#[test]
fn split_be() {
let value = 0xabcd;
let (low, high) = split_word_lh(value);
assert_eq!(low, 0xcd);
assert_eq!(high, 0xab);
}
}
impl Instruction {
pub fn to_bytes(&self) -> Vec<u8> {
match self {
ADC(mode) => {
match mode {
Immediate(value) =>
vec![ISA_OP_ADC_I, *value],
ZeroPage(offset) =>
vec![ISA_OP_ADC_Z, *offset],
ZeroPageX(value) =>
vec![ISA_OP_ADC_ZX, *value],
Absolute(offset) => {
let high = ((offset & 0xff00) >> 8) as u8;
let low = (offset & 0x00ff) as u8;
vec![ISA_OP_ADC_ABS, low, high]
}
AbsoluteX(offset) => {
let high = ((offset & 0xff00) >> 8) as u8;
let low = (offset & 0x00ff) as u8;
vec![ISA_OP_ADC_ABSX, low, high]
}
AbsoluteY(offset) => {
let high = ((offset & 0xff00) >> 8) as u8;
let low = (offset & 0x00ff) as u8;
vec![ISA_OP_ADC_ABSY, low, high]
}
IndirectX(offset) =>
vec![ISA_OP_ADC_INDX, *offset],
IndirectY(offset) =>
vec![ISA_OP_ADC_INDY, *offset],
_ => { vec![] }
}
}
AND(mode) => {
match mode {
Immediate(value) => vec![ISA_OP_AND_I, *value],
ZeroPage(value) => vec![ISA_OP_AND_Z, *value],
ZeroPageX(value) => vec![ISA_OP_AND_ZX, *value],
Absolute(offset) => {
let (h, l) = split_word_hl(*offset);
vec![ISA_OP_AND_ABS, l, h]
}
AbsoluteX(offset) => {
let (h, l) = split_word_hl(*offset);
vec![ISA_OP_AND_ABSX, l, h]
}
AbsoluteY(offset) => {
let (h, l) = split_word_hl(*offset);
vec![ISA_OP_AND_ABSY, l, h]
}
IndirectX(value) => vec![ISA_OP_AND_INDX, *value],
IndirectY(value) => vec![ISA_OP_AND_INDY, *value],
_ => vec![]
}
}
ASL(mode) => {
match mode {
AddressMode::Accumulator => {
vec![ISA_OP_ASL_A]
}
ZeroPage(value) => {
vec![ISA_OP_ASL_Z, *value]
}
ZeroPageX(value) => {
vec![ISA_OP_ASL_ZX, *value]
}
Absolute(offset) => {
let (h, l) = split_word_hl(*offset);
vec![ISA_OP_ASL_ABS, l, h]
}
AbsoluteX(offset) => {
let (h, l) = split_word_hl(*offset);
vec![ISA_OP_ASL_ABSX, l, h]
}
_ => vec![ISA_OP_NOP]
}
}
BCC(mode) => {
match mode {
Immediate(value) => {
vec![ISA_OP_BCC, *value]
}
_ => vec![ISA_OP_NOP]
}
}
BCS(mode) => {
match mode {
Immediate(value) => {
vec![ISA_OP_BCS, *value]
}
_ => vec![ISA_OP_NOP]
}
}
BEQ(mode) => {
match mode {
Immediate(value) => {
vec![ISA_OP_BEQ, *value]
}
_ => vec![ISA_OP_NOP]
}
}
BIT(mode) => {
match mode {
Absolute(offset) => {
let (h, l) = split_word_hl(*offset);
vec![ISA_OP_BIT_ABS, l, h]
}
ZeroPage(value) => vec![ISA_OP_BIT_ZP, *value],
_ => vec![ISA_OP_NOP]
}
}
BMI(mode) => {
match mode {
Immediate(value) => vec![ISA_OP_BMI, *value],
_ => vec![ISA_OP_NOP]
}
}
BNE(mode) => {
match mode {
Immediate(value) => vec![ISA_OP_BNE, *value],
_ => vec![ISA_OP_NOP]
}
}
BPL(mode) => {
match mode {
Immediate(value) => vec![ISA_OP_BPL, *value],
_ => vec![ISA_OP_NOP]
}
}
BRK => vec![ISA_OP_BRK],
BVC(mode) => {
match mode {
Immediate(value) => vec![ISA_OP_BVC, *value],
_ => vec![ISA_OP_NOP]
}
}
BVS(mode) => {
match mode {
Immediate(value) => vec![ISA_OP_BVS, *value],
_ => vec![ISA_OP_NOP]
}
}
CLC => vec![ISA_OP_CLC],
CLD => vec![ISA_OP_CLD],
CLI => vec![ISA_OP_CLI],
CLV => vec![ISA_OP_CLV],
CMP(mode) => {
match mode {
Immediate(value) => vec![ISA_OP_CMP_I, *value],
ZeroPage(value) => vec![ISA_OP_CMP_ZP, *value],
ZeroPageX(value) => vec![ISA_OP_CMP_ZPX, *value],
Absolute(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_CMP_ABS, l, h]
}
AbsoluteX(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_CMP_ABSX, l, h]
}
IndirectX(value) => vec![ISA_OP_CMP_INDX, *value],
IndirectY(value) => vec![ISA_OP_CMP_INDY, *value],
_ => vec![ISA_OP_NOP]
}
}
CPX(mode) => {
match mode {
Immediate(value) => vec![ISA_OP_CPX_I, *value],
ZeroPage(value) => vec![ISA_OP_CPX_ZP, *value],
Absolute(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_CPX_ABS, l, h]
}
_ => vec![ISA_OP_NOP]
}
}
CPY(mode) => {
match mode {
Immediate(value) => vec![ISA_OP_CPY_I, *value],
ZeroPage(value) => vec![ISA_OP_CPY_ZP, *value],
Absolute(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_CPY_ABS, l, h]
}
_ => vec![ISA_OP_NOP]
}
}
DEC(mode) => match mode {
ZeroPage(value) => vec![ISA_OP_DEC_ZP, *value],
ZeroPageX(value) => vec![ISA_OP_DEC_ZPX, *value],
Absolute(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_DEC_ABS, l, h]
}
AbsoluteX(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_DEC_ABSX, l, h]
}
_ => vec![ISA_OP_NOP]
}
DEX => vec![ISA_OP_DEX],
DEY => vec![ISA_OP_DEY],
EOR(mode) => {
match mode {
Immediate(value) => vec![ISA_OP_EOR_I, *value],
ZeroPage(value) => vec![ISA_OP_EOR_ZP, *value],
ZeroPageX(value) => vec![ISA_OP_EOR_ZPX, *value],
Absolute(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_EOR_ABS, l, h]
}
AbsoluteX(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_EOR_ABSX, l, h]
}
AbsoluteY(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_EOR_ABSY, l, h]
}
IndirectX(value) => vec![ISA_OP_EOR_INDX, *value],
IndirectY(value) => vec![ISA_OP_EOR_INDY, *value],
_ => vec![ISA_OP_NOP]
}
}
INC(mode) => {
match mode {
ZeroPage(value) => vec![ISA_OP_INC_ZP, *value],
ZeroPageX(value) => vec![ISA_OP_INC_ZPX, *value],
Absolute(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_INC_ABS, l, h]
}
AbsoluteX(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_INC_ABSX, l, h]
}
_ => vec![ISA_OP_NOP]
}
}
INX => vec![ISA_OP_INX],
INY => vec![ISA_OP_INY],
JMP(mode) => {
match mode {
Absolute(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_JMP_ABS, l, h]
}
IndirectX(value) => {
vec![ISA_OP_JMP_IND, *value]
}
_ => vec![ISA_OP_NOP]
}
}
JSR(mode) => {
match mode {
Immediate(value) => vec![ISA_OP_JSR, *value],
_ => vec![ISA_OP_NOP]
}
}
LDA(mode) => {
match mode {
Immediate(value) => vec![ISA_OP_LDA_I, *value],
ZeroPage(value) => vec![ISA_OP_LDA_Z, *value],
ZeroPageX(value) => vec![ISA_OP_LDA_ZX, *value],
Absolute(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_LDA_ABS, l, h]
}
AbsoluteX(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_LDA_ABSX, l, h]
}
AbsoluteY(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_LDA_ABSY, l, h]
}
IndirectX(value) => vec![ISA_OP_LDA_INDX, *value],
IndirectY(value) => vec![ISA_OP_LDA_INDY, *value],
_ => vec![ISA_OP_NOP]
}
}
LDX(mode) => {
match mode {
Immediate(value) => vec![ISA_OP_LDX_I, *value],
ZeroPage(value) => vec![ISA_OP_LDX_ZP, *value],
ZeroPageY(value) => vec![ISA_OP_LDX_ZPY, *value],
Absolute(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_LDX_ABS, l, h]
}
AbsoluteY(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_LDX_ABSY, l, h]
}
_ => vec![ISA_OP_NOP]
}
}
LDY(mode) => {
match mode {
Immediate(value) => vec![ISA_OP_LDY_I, *value],
ZeroPage(value) => vec![ISA_OP_LDY_ZP, *value],
ZeroPageX(value) => vec![ISA_OP_LDY_ZPX, *value],
Absolute(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_LDY_ABS, l, h]
}
AbsoluteY(offset) => {
let (l, h) = split_word_lh(*offset);
vec![ISA_OP_LDY_ABSX, l, h]
}
_ => vec![ISA_OP_NOP]
}}
// LSR(_) => {}
NOP => vec![ISA_OP_NOP],
// ORA(_) => {}
PHA => vec![ISA_OP_PHA],
PHP => vec![ISA_OP_PHP],
PLA => vec![ISA_OP_PLA],
PLP => vec![ISA_OP_PLP],
// ROL(_) => {}
// ROR(_) => {}
RTI => vec![ISA_OP_RTI],
RTS => vec![ISA_OP_RTS],
// SBC(_) => {}
SEC => vec![ISA_OP_SEC],
SED => vec![ISA_OP_SED],
SEI => vec![ISA_OP_SEI],
// STA(_) => {}
STX(mode) => {
match mode {
ZeroPage(value) => {
vec![ISA_OP_STX_ZP, *value]
}
ZeroPageX(value) => {
vec![ISA_OP_STX_ZPX, *value]
}
Absolute(offset) => {
let (h, l) = split_word_hl(*offset);
vec![ISA_OP_STX_ABS, l, h]
}
_ => vec![ISA_OP_NOP]
}
}
STY(mode) => {
match mode {
ZeroPage(value) => {
vec![ISA_OP_STY_ZP, *value]
}
ZeroPageX(value) => {
vec![ISA_OP_STY_ZPX, *value]
}
Absolute(offset) => {
let (h, l) = split_word_hl(*offset);
vec![ISA_OP_STY_ABS, l, h]
}
_ => vec![ISA_OP_NOP]
}
}
TAX => vec![ISA_OP_TAX],
TAY => vec![ISA_OP_TAY],
TSX => vec![ISA_OP_TSX],
TXA => vec![ISA_OP_TXA],
TXS => vec![ISA_OP_TXS],
TYA => vec![ISA_OP_TYA],
_ => { vec![] }
}
}
}
-42
View File
@@ -1,42 +0,0 @@
use crate::address_mode::AddressMode;
use crate::address_mode::AddressMode::Implied;
use crate::instruction::Instruction;
use crate::instruction::Instruction::*;
impl Instruction {
pub fn to_string(&self) -> String {
let mode = match self {
ADC(newmode) | AND(newmode) | ASL(newmode) |
BCC(newmode) | BCS(newmode) | BEQ(newmode) |
BIT(newmode) | BMI(newmode) | BNE(newmode) |
BPL(newmode) | BVC(newmode) | BVS(newmode) |
CMP(newmode) | CPX(newmode) | CPY(newmode) |
DEC(newmode) | EOR(newmode) | INC(newmode) |
JMP(newmode) | JSR(newmode) | LDA(newmode) |
LDX(newmode) | LDY(newmode) | LSR(newmode) |
ORA(newmode) | ROL(newmode) | ROR(newmode) |
SBC(newmode) | STA(newmode) | STX(newmode) |
STY(newmode) => newmode,
_ => &Implied
};
Instruction::format(mode, &self.stub())
}
fn format(mode: &AddressMode, prefix: &str) -> String {
let suffix = match mode {
AddressMode::Implied => "",
AddressMode::Accumulator => " A",
AddressMode::Immediate(value) => &*format!(" #${value:02x}"),
AddressMode::ZeroPage(value) => &*format!(" ${value:02x}"),
AddressMode::ZeroPageX(value) => &*format!(" ${value:02x},X"),
AddressMode::Absolute(offset) => &*format!(" ${offset:04x}"),
AddressMode::AbsoluteX(offset) => &*format!(" ${offset:04x},X"),
AddressMode::AbsoluteY(offset) => &*format!(" ${offset:04x},Y"),
AddressMode::IndirectX(value) => &*format!(" (${value:02x},X)"),
AddressMode::IndirectY(value) => &*format!(" (${value:02x}),Y"),
AddressMode::ZeroPageY(value) => &*format!(" ${value:02x},Y")
};
format!("{}{}", prefix, suffix)
}
}
+23
View File
@@ -0,0 +1,23 @@
use log::debug;
use crate::address_mode::AddressMode::*;
use crate::constants::constants_isa_op::*;
fn join_word(low: u8, high: u8) -> u16 {
((high as u16) << 8) | low as u16
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_join_word() {
let low: u8 = 0xcd;
let high: u8 = 0xab;
assert_eq!(
join_word(low, high),
0xabcd
);
}
}
+7
View File
@@ -0,0 +1,7 @@
use crate::address_mode::AddressMode;
use crate::address_mode::AddressMode::*;
use crate::mos6502flags::Mos6502Flag::*;
mod from_bytes;
mod to_bytes;
mod to_string;
+38
View File
@@ -0,0 +1,38 @@
use crate::address_mode::AddressMode;
use crate::address_mode::AddressMode::{Absolute, AbsoluteX, AbsoluteY, Immediate, IndirectX, IndirectY, ZeroPage, ZeroPageX, ZeroPageY};
use crate::constants::constants_isa_op::*;
fn split_word_hl(to_split: u16) -> (u8, u8) {
let low = (to_split & 0xff) as u8;
let high = ((to_split & 0xff00) >> 8) as u8;
(high, low)
}
fn split_word_lh(to_split: u16) -> (u8, u8) {
let low = (to_split & 0xff) as u8;
let high = ((to_split & 0xff00) >> 8) as u8;
(low, high)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn split_le() {
let value = 0xabcd;
let (high, low) = split_word_hl(value);
assert_eq!(low, 0xcd);
assert_eq!(high, 0xab);
}
#[test]
fn split_be() {
let value = 0xabcd;
let (low, high) = split_word_lh(value);
assert_eq!(low, 0xcd);
assert_eq!(high, 0xab);
}
}
+18
View File
@@ -0,0 +1,18 @@
fn format(mode: &AddressMode, prefix: &str) -> String {
// let suffix = match mode {
// AddressMode::Implied => "",
// AddressMode::Accumulator => " A",
// AddressMode::Immediate(value) => &*format!(" #${value:02x}"),
// AddressMode::ZeroPage(value) => &*format!(" ${value:02x}"),
// AddressMode::ZeroPageX(value) => &*format!(" ${value:02x},X"),
// AddressMode::Absolute(offset) => &*format!(" ${offset:04x}"),
// AddressMode::AbsoluteX(offset) => &*format!(" ${offset:04x},X"),
// AddressMode::AbsoluteY(offset) => &*format!(" ${offset:04x},Y"),
// AddressMode::IndirectX(value) => &*format!(" (${value:02x},X)"),
// AddressMode::IndirectY(value) => &*format!(" (${value:02x}),Y"),
// AddressMode::ZeroPageY(value) => &*format!(" ${value:02x},Y")
// };
// format!("{}{}", prefix, suffix)
prefix.to_string()
}
+938
View File
@@ -0,0 +1,938 @@
use crate::address_mode::AddressMode;
use crate::constants::constants_isa_op::{ISA_OP_ADC_ABS, ISA_OP_ADC_ABSX, ISA_OP_ADC_ABSY, ISA_OP_ADC_I, ISA_OP_ADC_INDX, ISA_OP_ADC_INDY, ISA_OP_ADC_Z, ISA_OP_ADC_ZX, ISA_OP_AND_ABS, ISA_OP_AND_ABSX, ISA_OP_AND_ABSY, ISA_OP_AND_I, ISA_OP_AND_INDX, ISA_OP_AND_INDY, ISA_OP_AND_Z, ISA_OP_AND_ZX, ISA_OP_ASL_A, ISA_OP_ASL_ABS, ISA_OP_ASL_ABSX, ISA_OP_ASL_Z, ISA_OP_ASL_ZX, ISA_OP_BCC, ISA_OP_BCS, ISA_OP_BEQ, ISA_OP_BIT_ABS, ISA_OP_BIT_ZP, ISA_OP_BMI, ISA_OP_BNE, ISA_OP_BPL, ISA_OP_BRK, ISA_OP_BVC, ISA_OP_BVS, ISA_OP_CLC, ISA_OP_CLD, ISA_OP_CLI, ISA_OP_CLV, ISA_OP_CMP_ABS, ISA_OP_CMP_ABSX, ISA_OP_CMP_ABSY, ISA_OP_CMP_I, ISA_OP_CMP_INDX, ISA_OP_CMP_INDY, ISA_OP_CMP_ZP, ISA_OP_CMP_ZPX, ISA_OP_CPX_ABS, ISA_OP_CPX_I, ISA_OP_CPX_ZP, ISA_OP_CPY_ABS, ISA_OP_CPY_I, ISA_OP_CPY_ZP, ISA_OP_DEC_ABS, ISA_OP_DEC_ABSX, ISA_OP_DEC_ZP, ISA_OP_DEC_ZPX, ISA_OP_DEX, ISA_OP_DEY, ISA_OP_EOR_ABS, ISA_OP_EOR_ABSX, ISA_OP_EOR_ABSY, ISA_OP_EOR_I, ISA_OP_EOR_INDX, ISA_OP_EOR_ZP, ISA_OP_EOR_ZPX, ISA_OP_INC_ABS, ISA_OP_INC_ABSX, ISA_OP_INC_ZP, ISA_OP_INC_ZPX, ISA_OP_INX, ISA_OP_INY, ISA_OP_JMP_ABS, ISA_OP_JMP_IND, ISA_OP_JSR, ISA_OP_LDA_ABS, ISA_OP_LDA_ABSX, ISA_OP_LDA_ABSY, ISA_OP_LDA_I, ISA_OP_LDA_INDX, ISA_OP_LDA_INDY, ISA_OP_LDA_Z, ISA_OP_LDA_ZX, ISA_OP_LDX_ABS, ISA_OP_LDX_ABSY, ISA_OP_LDX_I, ISA_OP_LDX_ZP, ISA_OP_LDX_ZPY, ISA_OP_LDY_ABS, ISA_OP_LDY_ABSX, ISA_OP_LDY_I, ISA_OP_LDY_ZP, ISA_OP_LDY_ZPX, ISA_OP_LSR_A, ISA_OP_LSR_ABS, ISA_OP_LSR_ABSX, ISA_OP_LSR_ZP, ISA_OP_LSR_ZPX, ISA_OP_NOP, ISA_OP_ORA_ABS, ISA_OP_ORA_ABSY, ISA_OP_ORA_I, ISA_OP_ORA_INDX, ISA_OP_ORA_INDY, ISA_OP_ORA_ZP, ISA_OP_ORA_ZPX, ISA_OP_PHA, ISA_OP_PHP, ISA_OP_PLA, ISA_OP_PLP, ISA_OP_ROL_A, ISA_OP_ROL_ABS, ISA_OP_ROL_ABSX, ISA_OP_ROL_ZP, ISA_OP_ROL_ZPX, ISA_OP_ROR_A, ISA_OP_ROR_ABS, ISA_OP_ROR_ABSX, ISA_OP_ROR_ZP, ISA_OP_ROR_ZPX, ISA_OP_RTI, ISA_OP_RTS, ISA_OP_SBC_ABS, ISA_OP_SBC_ABSX, ISA_OP_SBC_ABSY, ISA_OP_SBC_I, ISA_OP_SBC_INDX, ISA_OP_SBC_INDY, ISA_OP_SBC_ZP, ISA_OP_SBC_ZPX, ISA_OP_SEC, ISA_OP_SED, ISA_OP_SEI, ISA_OP_STA_ABS, ISA_OP_STA_ABSX, ISA_OP_STA_ABSY, ISA_OP_STA_INDX, ISA_OP_STA_INDY, ISA_OP_STA_ZP, ISA_OP_STA_ZPX, ISA_OP_STX_ABS, ISA_OP_STX_ZP, ISA_OP_STX_ZPY, ISA_OP_STY_ABS, ISA_OP_STY_ZP, ISA_OP_STY_ZPX, ISA_OP_TAX, ISA_OP_TAY, ISA_OP_TSX, ISA_OP_TXA, ISA_OP_TXS, ISA_OP_TYA};
use crate::op_info::OpInfo;
use crate::operation::Operation;
use crate::operation::Operation::*;
pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
let mut table: [Option<OpInfo>; 256] = [const { None }; 256];
table[ISA_OP_ADC_I as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_ADC_Z as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_ADC_ZX as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_ADC_ABS as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_ADC_ABSX as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 4,
});
table[ISA_OP_ADC_ABSY as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 4,
});
table[ISA_OP_ADC_INDX as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_ADC_INDY as usize] = Some(OpInfo {
operation: ADC,
mode: AddressMode::IndirectY,
length: 2,
cycles: 5,
});
table[ISA_OP_AND_I as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_AND_Z as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_AND_ZX as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_AND_ABS as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_AND_ABSX as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 4,
});
table[ISA_OP_AND_ABSY as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 4,
});
table[ISA_OP_AND_INDX as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_AND_INDY as usize] = Some(OpInfo {
operation: AND,
mode: AddressMode::IndirectY,
length: 2,
cycles: 5,
});
table[ISA_OP_ASL_A as usize] = Some(OpInfo {
operation: ASL,
mode: AddressMode::Accumulator,
length: 1,
cycles: 2,
});
table[ISA_OP_ASL_Z as usize] = Some(OpInfo {
operation: ASL,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 5,
});
table[ISA_OP_ASL_ZX as usize] = Some(OpInfo {
operation: ASL,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 6,
});
table[ISA_OP_ASL_ABS as usize] = Some(OpInfo {
operation: ASL,
mode: AddressMode::Absolute,
length: 3,
cycles: 6,
});
table[ISA_OP_ASL_ABSX as usize] = Some(OpInfo {
operation: ASL,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 7,
});
table[ISA_OP_BCC as usize] = Some(OpInfo {
operation: BCC,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_BCS as usize] = Some(OpInfo {
operation: BCS,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_BEQ as usize] = Some(OpInfo {
operation: BEQ,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_BIT_ZP as usize] = Some(OpInfo {
operation: BIT,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_BIT_ABS as usize] = Some(OpInfo {
operation: BIT,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_BMI as usize] = Some(OpInfo {
operation: BMI,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_BNE as usize] = Some(OpInfo {
operation: BNE,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_BPL as usize] = Some(OpInfo {
operation: Operation::BPL,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_BRK as usize] = Some(OpInfo {
operation: BRK,
mode: AddressMode::Implied,
length: 1,
cycles: 7,
});
table[ISA_OP_BVC as usize] = Some(OpInfo {
operation: BVC,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_BVS as usize] = Some(OpInfo {
operation: BVS,
mode: AddressMode::Implied,
length: 2,
cycles: 2,
});
table[ISA_OP_CLC as usize] = Some(OpInfo {
operation: CLC,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_CLD as usize] = Some(OpInfo {
operation: CLD,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_CLI as usize] = Some(OpInfo {
operation: CLI,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_CLV as usize] = Some(OpInfo {
operation: CLV,
mode: AddressMode::Implied,
length: 2,
cycles: 1,
});
table[ISA_OP_CMP_I as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_CMP_ZP as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_CMP_ZPX as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_CMP_ABS as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_CMP_ABSX as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::AbsoluteX,
length: 2,
cycles: 4,
});
table[ISA_OP_CMP_ABSY as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::AbsoluteY,
length: 2,
cycles: 4,
});
table[ISA_OP_CMP_INDX as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_CMP_INDY as usize] = Some(OpInfo {
operation: CMP,
mode: AddressMode::IndirectY,
length: 2,
cycles: 5,
});
table[ISA_OP_CPX_I as usize] = Some(OpInfo {
operation: CPX,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_CPX_ZP as usize] = Some(OpInfo {
operation: CPX,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_CPX_ABS as usize] = Some(OpInfo {
operation: CPX,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_CPY_I as usize] = Some(OpInfo {
operation: CPY,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_CPY_ZP as usize] = Some(OpInfo {
operation: CPY,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_CPY_ABS as usize] = Some(OpInfo {
operation: CPY,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_DEC_ZP as usize] = Some(OpInfo {
operation: DEC,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 5,
});
table[ISA_OP_DEC_ZPX as usize] = Some(OpInfo {
operation: DEC,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 6,
});
table[ISA_OP_DEC_ABS as usize] = Some(OpInfo {
operation: DEC,
mode: AddressMode::Absolute,
length: 3,
cycles: 6,
});
table[ISA_OP_DEC_ABSX as usize] = Some(OpInfo {
operation: DEC,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 7,
});
table[ISA_OP_DEX as usize] = Some(OpInfo {
operation: DEX,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_DEY as usize] = Some(OpInfo {
operation: DEY,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_EOR_I as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_EOR_ZP as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_EOR_ZPX as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_EOR_ABS as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_EOR_ABSX as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 4,
});
table[ISA_OP_EOR_ABSX as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 4,
});
table[ISA_OP_EOR_INDX as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_EOR_ABSY as usize] = Some(OpInfo {
operation: EOR,
mode: AddressMode::IndirectY,
length: 2,
cycles: 5,
});
table[ISA_OP_INC_ZP as usize] = Some(OpInfo {
operation: INC,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 5,
});
table[ISA_OP_INC_ZPX as usize] = Some(OpInfo {
operation: INC,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 6,
});
table[ISA_OP_INC_ABS as usize] = Some(OpInfo {
operation: INC,
mode: AddressMode::Absolute,
length: 3,
cycles: 6,
});
table[ISA_OP_INC_ABSX as usize] = Some(OpInfo {
operation: INC,
mode: AddressMode::ZeroPageX,
length: 3,
cycles: 7,
});
table[ISA_OP_INX as usize] = Some(OpInfo {
operation: INX,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_INY as usize] = Some(OpInfo {
operation: INY,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_JMP_ABS as usize] = Some(OpInfo {
operation: JMP,
mode: AddressMode::Absolute,
length: 3,
cycles: 3,
});
table[ISA_OP_JMP_IND as usize] = Some(OpInfo {
operation: JMP,
mode: AddressMode::Indirect,
length: 3,
cycles: 5,
});
table[ISA_OP_JSR as usize] = Some(OpInfo {
operation: JSR,
mode: AddressMode::Absolute,
length: 3,
cycles: 6,
});
table[ISA_OP_LDA_I as usize] = Some(OpInfo {
operation: Operation::LDA,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_LDA_Z as usize] = Some(OpInfo {
operation: LDA,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_LDA_ZX as usize] = Some(OpInfo {
operation: LDA,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_LDA_ABS as usize] = Some(OpInfo {
operation: Operation::LDA,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_LDA_ABSX as usize] = Some(OpInfo {
operation: LDA,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 4,
});
table[ISA_OP_LDA_ABSY as usize] = Some(OpInfo {
operation: LDA,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 4,
});
table[ISA_OP_LDA_INDX as usize] = Some(OpInfo {
operation: Operation::LDA,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_LDA_INDY as usize] = Some(OpInfo {
operation: LDA,
mode: AddressMode::IndirectY,
length: 2,
cycles: 5,
});
table[ISA_OP_LDX_I as usize] = Some(OpInfo {
operation: Operation::LDX,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_LDX_ZP as usize] = Some(OpInfo {
operation: Operation::LDX,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_LDX_ZPY as usize] = Some(OpInfo {
operation: LDX,
mode: AddressMode::ZeroPageY,
length: 2,
cycles: 4,
});
table[ISA_OP_LDX_ABS as usize] = Some(OpInfo {
operation: Operation::LDX,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_LDX_ABSY as usize] = Some(OpInfo {
operation: Operation::LDX,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 4,
});
table[ISA_OP_LDY_I as usize] = Some(OpInfo {
operation: Operation::LDY,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_LDY_ZP as usize] = Some(OpInfo {
operation: Operation::LDY,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_LDY_ZPX as usize] = Some(OpInfo {
operation: Operation::LDY,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_LDY_ABS as usize] = Some(OpInfo {
operation: Operation::LDY,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_LDY_ABSX as usize] = Some(OpInfo {
operation: Operation::LDY,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 4,
});
table[ISA_OP_LSR_A as usize] = Some(OpInfo {
operation: Operation::LSR,
mode: AddressMode::Accumulator,
length: 1,
cycles: 2,
});
table[ISA_OP_LSR_ZP as usize] = Some(OpInfo {
operation: Operation::LSR,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 5,
});
table[ISA_OP_LSR_ZPX as usize] = Some(OpInfo {
operation: Operation::LSR,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 6,
});
table[ISA_OP_LSR_ABS as usize] = Some(OpInfo {
operation: Operation::LSR,
mode: AddressMode::Absolute,
length: 3,
cycles: 6,
});
table[ISA_OP_LSR_ABSX as usize] = Some(OpInfo {
operation: Operation::LSR,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 7,
});
table[ISA_OP_NOP as usize] = Some(OpInfo {
operation: Operation::NOP,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_ORA_I as usize] = Some(OpInfo {
operation: Operation::ORA,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_ORA_ZP as usize] = Some(OpInfo {
operation: Operation::ORA,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_ORA_ZPX as usize] = Some(OpInfo {
operation: Operation::ORA,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_ORA_ABS as usize] = Some(OpInfo {
operation: Operation::ORA,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_ORA_ABSY as usize] = Some(OpInfo {
operation: Operation::ORA,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 4,
});
table[ISA_OP_ORA_INDX as usize] = Some(OpInfo {
operation: Operation::ORA,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_ORA_INDY as usize] = Some(OpInfo {
operation: Operation::ORA,
mode: AddressMode::IndirectY,
length: 2,
cycles: 5,
});
table[ISA_OP_PHA as usize] = Some(OpInfo {
operation: PHA,
mode: AddressMode::Implied,
length: 1,
cycles: 3,
});
table[ISA_OP_PHP as usize] = Some(OpInfo {
operation: Operation::PHP,
mode: AddressMode::Implied,
length: 1,
cycles: 3,
});
table[ISA_OP_PLA as usize] = Some(OpInfo {
operation: Operation::PLA,
mode: AddressMode::Implied,
length: 1,
cycles: 4,
});
table[ISA_OP_PLP as usize] = Some(OpInfo {
operation: Operation::PLP,
mode: AddressMode::Implied,
length: 1,
cycles: 4,
});
table[ISA_OP_ROL_A as usize] = Some(OpInfo {
operation: Operation::ROL,
mode: AddressMode::Accumulator,
length: 1,
cycles: 2,
});
table[ISA_OP_ROL_ZP as usize] = Some(OpInfo {
operation: Operation::ROL,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 5,
});
table[ISA_OP_ROL_ZPX as usize] = Some(OpInfo {
operation: Operation::ROL,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 6,
});
table[ISA_OP_ROL_ABS as usize] = Some(OpInfo {
operation: Operation::ROL,
mode: AddressMode::Absolute,
length: 3,
cycles: 6,
});
table[ISA_OP_ROL_ABSX as usize] = Some(OpInfo {
operation: Operation::ROL,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 7,
});
table[ISA_OP_ROR_A as usize] = Some(OpInfo {
operation: Operation::ROR,
mode: AddressMode::Accumulator,
length: 1,
cycles: 2
});
table[ISA_OP_ROR_ZP as usize] = Some(OpInfo {
operation: Operation::ROR,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 5,
});
table[ISA_OP_ROR_ZPX as usize] = Some(OpInfo {
operation: Operation::ROR,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 6,
});
table[ISA_OP_ROR_ABS as usize] = Some(OpInfo {
operation: Operation::ROR,
mode: AddressMode::Absolute,
length: 3,
cycles: 6,
});
table[ISA_OP_ROR_ABSX as usize] = Some(OpInfo {
operation: Operation::ROR,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 7,
});
table[ISA_OP_RTI as usize] = Some(OpInfo {
operation: Operation::RTI,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_RTS as usize] = Some(OpInfo {
operation: Operation::RTS,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_SBC_I as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::Immediate,
length: 2,
cycles: 2,
});
table[ISA_OP_SBC_ZP as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_SBC_ZPX as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_SBC_ABS as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_SBC_ABSX as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 4,
});
table[ISA_OP_SBC_ABSY as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 4,
});
table[ISA_OP_SBC_INDX as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_SBC_INDY as usize] = Some(OpInfo {
operation: Operation::SBC,
mode: AddressMode::IndirectY,
length: 2,
cycles: 5,
});
table[ISA_OP_SEC as usize] = Some(OpInfo {
operation: SEC,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_SED as usize] = Some(OpInfo {
operation: Operation::SED,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_SEI as usize] = Some(OpInfo {
operation: Operation::SEI,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_STA_ZP as usize] = Some(OpInfo {
operation: Operation::STA,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_STA_ZPX as usize] = Some(OpInfo {
operation: Operation::STA,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_STA_ABS as usize] = Some(OpInfo {
operation: Operation::STA,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_STA_ABSX as usize] = Some(OpInfo {
operation: STA,
mode: AddressMode::AbsoluteX,
length: 3,
cycles: 5,
});
table[ISA_OP_STA_ABSY as usize] = Some(OpInfo {
operation: Operation::STA,
mode: AddressMode::AbsoluteY,
length: 3,
cycles: 5,
});
table[ISA_OP_STA_INDX as usize] = Some(OpInfo {
operation: Operation::STA,
mode: AddressMode::IndirectX,
length: 2,
cycles: 6,
});
table[ISA_OP_STA_INDY as usize] = Some(OpInfo {
operation: Operation::STA,
mode: AddressMode::IndirectY,
length: 2,
cycles: 6,
});
table[ISA_OP_STX_ZP as usize] = Some(OpInfo {
operation: Operation::STX,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_STX_ZPY as usize] = Some(OpInfo {
operation: Operation::STX,
mode: AddressMode::ZeroPageY,
length: 2,
cycles: 4,
});
table[ISA_OP_STX_ABS as usize] = Some(OpInfo {
operation: Operation::STX,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_STY_ZP as usize] = Some(OpInfo {
operation: Operation::STY,
mode: AddressMode::ZeroPage,
length: 2,
cycles: 3,
});
table[ISA_OP_STY_ZPX as usize] = Some(OpInfo {
operation: Operation::STY,
mode: AddressMode::ZeroPageX,
length: 2,
cycles: 4,
});
table[ISA_OP_STY_ABS as usize] = Some(OpInfo {
operation: Operation::STY,
mode: AddressMode::Absolute,
length: 3,
cycles: 4,
});
table[ISA_OP_TAX as usize] = Some(OpInfo {
operation: Operation::TAX,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_TAY as usize] = Some(OpInfo {
operation: TAY,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_TSX as usize] = Some(OpInfo {
operation: TSX,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_TXA as usize] = Some(OpInfo {
operation: Operation::TXA,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_TXS as usize] = Some(OpInfo {
operation: Operation::TXS,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table[ISA_OP_TYA as usize] = Some(OpInfo {
operation: TYA,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
});
table
};
-76
View File
@@ -1,76 +0,0 @@
use crate::address_mode::AddressMode::*;
use crate::instruction::Instruction;
use crate::instruction::Instruction::*;
pub struct Decoder {}
impl Decoder {
/// decode
///
/// Returns the decoded instruction or a NOP.
/// NOP will be returned when an instruction without a valid parameter
/// and more data is required to decode.
pub fn decode(decode_from: Vec<u8>) -> Instruction {
Instruction::from_bytes(decode_from)
}
}
#[cfg(test)]
mod test {
use crate::constants::constants_isa_op::{ISA_OP_ADC_ABS, ISA_OP_ADC_ABSX, ISA_OP_ADC_ABSY, ISA_OP_ADC_I, ISA_OP_ADC_INDX, ISA_OP_ADC_INDY, ISA_OP_ADC_Z, ISA_OP_ADC_ZX, ISA_OP_AND_ABS, ISA_OP_AND_I, ISA_OP_AND_Z, ISA_OP_AND_ZX, ISA_OP_ASL_A, ISA_OP_ASL_ABS, ISA_OP_ASL_ABSX, ISA_OP_ASL_Z, ISA_OP_ASL_ZX, ISA_OP_BCC, ISA_OP_BEQ, ISA_OP_BIT_ABS, ISA_OP_BIT_ZP, ISA_OP_BMI, ISA_OP_BNE, ISA_OP_BPL, ISA_OP_BRK, ISA_OP_BVC, ISA_OP_BVS};
use super::*;
#[test]
fn valid_decodes() {
let params = vec![
(vec![ISA_OP_ADC_I, 0xab], ADC(Immediate(0xab))),
(vec![ISA_OP_ADC_Z, 0xab], ADC(ZeroPage(0xab))),
(vec![ISA_OP_ADC_ZX, 0xab], ADC(ZeroPageX(0xab))),
(vec![ISA_OP_ADC_ABS, 0xab, 0xcd], ADC(Absolute(0xcdab))),
(vec![ISA_OP_ADC_ABSX, 0xcd, 0xab], ADC(AbsoluteX(0xabcd))),
(vec![ISA_OP_ADC_ABSY, 0xcd, 0xab], ADC(AbsoluteY(0xabcd))),
(vec![ISA_OP_ADC_INDX, 0xab], ADC(IndirectX(0xab))),
(vec![ISA_OP_ADC_INDY, 0xcd], ADC(IndirectY(0xcd))),
(vec![ISA_OP_AND_I, 0xab], AND(Immediate(0xab))),
(vec![ISA_OP_AND_Z, 0xab], AND(ZeroPage(0xab))),
(vec![ISA_OP_AND_ZX, 0xab], AND(ZeroPageX(0xab))),
(vec![ISA_OP_AND_ABS, 0xcd, 0xab], AND(Absolute(0xabcd))),
(vec![ISA_OP_ASL_A], ASL(Accumulator)),
(vec![ISA_OP_ASL_Z, 0xab], ASL(ZeroPage(0xab))),
(vec![ISA_OP_ASL_ZX, 0xab], ASL(ZeroPageX(0xab))),
(vec![ISA_OP_ASL_ABS, 0xab, 0xcd], ASL(Absolute(0xcdab))),
(vec![ISA_OP_ASL_ABSX, 0xab, 0xcd], ASL(AbsoluteX(0xcdab))),
(vec![ISA_OP_BCC, 0xab], BCC(Immediate(0xab))),
(vec![ISA_OP_BEQ, 0xab], BEQ(Immediate(0xab))),
(vec![ISA_OP_BIT_ZP, 0xab], BIT(ZeroPage(0xab))),
(vec![ISA_OP_BIT_ABS, 0xab, 0xcd], BIT(Absolute(0xcdab))),
(vec![ISA_OP_BMI, 0xab], BMI(Immediate(0xab))),
(vec![ISA_OP_BNE, 0xab], BNE(Immediate(0xab))),
(vec![ISA_OP_BPL, 0xab], BPL(Immediate(0xab))),
(vec![ISA_OP_BVC, 0xab], BVC(Immediate(0xab))),
(vec![ISA_OP_BVS, 0xab], BVS(Immediate(0xab))),
(vec![ISA_OP_BRK], BRK),
];
for (bytes, instruction) in params {
println!("Expecting {:?} to be {:?}", bytes, instruction);
assert_eq!(
Decoder::decode(bytes),
instruction
)
}
}
}
-129
View File
@@ -1,129 +0,0 @@
use crate::address_mode::AddressMode::*;
use crate::constants::constants_isa_op::ISA_OP_BCC;
use crate::instruction::Instruction;
use crate::instruction::Instruction::*;
pub struct Encoder {}
impl Encoder {
pub fn encode(to_encode: Instruction) -> Vec<u8> {
match to_encode {
// ADC(_) => {}
// AND(_) => {}
// ASL(_) => {}
BCC(mode) => {
match mode {
Immediate(address)=> {
vec![ISA_OP_BCC, address]
}
_ => NOP.to_bytes()
}
}
// BCS(_) => {}
// BEQ(_) => {}
// BIT(_) => {}
// BMI(_) => {}
// BNE(_) => {}
// BPL(_) => {}
// BRK => {}
// BVC(_) => {}
// BVS(_) => {}
// CLC => {}
// CLD => {}
// CLI => {}
// CLV => {}
// CMP(_) => {}
// CPX(_) => {}
// CPY(_) => {}
// DEC(_) => {}
// DEX => {}
// DEY => {}
// EOR(_) => {}
// INC(_) => {}
// INX => {}
// INY => {}
// JMP(_) => {}
// JSR(_) => {}
// LDA(_) => {}
// LDX(_) => {}
// LDY(_) => {}
// LSR(_) => {}
// NOP => {}
// ORA(_) => {}
// PHA => {}
// PHP => {}
// PLA => {}
// PLP => {}
// ROL(_) => {}
// ROR(_) => {}
// RTI => {}
// RTS => {}
// SBC(_) => {}
// SEC => {}
// SED => {}
// SEI => {}
// STA(_) => {}
// STX(_) => {}
// STY(_) => {}
// TAX => {}
// TAY => {}
// TSX => {}
// TXA => {}
// TXS => {}
// TYA => {}
_ => NOP.to_bytes()
}
}
}
#[cfg(test)]
mod test {
use crate::constants::constants_isa_op::{ISA_OP_ADC_ABS, ISA_OP_ADC_ABSX, ISA_OP_ADC_ABSY, ISA_OP_ADC_I, ISA_OP_ADC_INDX, ISA_OP_ADC_INDY, ISA_OP_ADC_Z, ISA_OP_ADC_ZX, ISA_OP_AND_ABS, ISA_OP_AND_I, ISA_OP_AND_Z, ISA_OP_AND_ZX, ISA_OP_ASL_A, ISA_OP_ASL_ABS, ISA_OP_ASL_ABSX, ISA_OP_ASL_Z, ISA_OP_ASL_ZX, ISA_OP_BEQ, ISA_OP_BIT_ABS, ISA_OP_BIT_ZP, ISA_OP_BMI, ISA_OP_BNE, ISA_OP_BPL, ISA_OP_BRK, ISA_OP_BVC, ISA_OP_BVS};
use super::*;
#[test]
fn adc_decode() {
let params = vec![
(vec![ISA_OP_ADC_I, 0xab], ADC(Immediate(0xab))),
(vec![ISA_OP_ADC_Z, 0xab], ADC(ZeroPage(0xab))),
(vec![ISA_OP_ADC_ZX, 0xab], ADC(ZeroPageX(0xab))),
(vec![ISA_OP_ADC_ABS, 0xab, 0xcd], ADC(Absolute(0xcdab))),
(vec![ISA_OP_ADC_ABSX, 0xcd, 0xab], ADC(AbsoluteX(0xabcd))),
(vec![ISA_OP_ADC_ABSY, 0xcd, 0xab], ADC(AbsoluteY(0xabcd))),
(vec![ISA_OP_ADC_INDX, 0xab], ADC(IndirectX(0xab))),
(vec![ISA_OP_ADC_INDY, 0xcd], ADC(IndirectY(0xcd))),
(vec![ISA_OP_AND_I, 0xab], AND(Immediate(0xab))),
(vec![ISA_OP_AND_Z, 0xab], AND(ZeroPage(0xab))),
(vec![ISA_OP_AND_ZX, 0xab], AND(ZeroPageX(0xab))),
(vec![ISA_OP_AND_ABS, 0xcd, 0xab], AND(Absolute(0xabcd))),
(vec![ISA_OP_ASL_A], ASL(Accumulator)),
(vec![ISA_OP_ASL_Z, 0xab], ASL(ZeroPage(0xab))),
(vec![ISA_OP_ASL_ZX, 0xab], ASL(ZeroPageX(0xab))),
(vec![ISA_OP_ASL_ABS, 0xab, 0xcd], ASL(Absolute(0xcdab))),
(vec![ISA_OP_ASL_ABSX, 0xab, 0xcd], ASL(AbsoluteX(0xcdab))),
(vec![ISA_OP_BCC, 0xab], BCC(Immediate(0xab))),
(vec![ISA_OP_BEQ, 0xab], BEQ(Immediate(0xab))),
(vec![ISA_OP_BIT_ZP, 0xab], BIT(ZeroPage(0xab))),
(vec![ISA_OP_BIT_ABS, 0xab, 0xcd], BIT(Absolute(0xcdab))),
(vec![ISA_OP_BMI, 0xab], BMI(Immediate(0xab))),
(vec![ISA_OP_BNE, 0xab], BNE(Immediate(0xab))),
(vec![ISA_OP_BPL, 0xab], BPL(Immediate(0xab))),
(vec![ISA_OP_BVC, 0xab], BVC(Immediate(0xab))),
(vec![ISA_OP_BVS, 0xab], BVS(Immediate(0xab))),
(vec![ISA_OP_BRK], BRK),
];
// for (bytes, instruction) in params {
// let encoded = Encoder::encode(bytes);
// assert_eq!(encoded, instruction.into());
// }
}
}
-18
View File
@@ -1,18 +0,0 @@
use crate::mos6502flags::Mos6502Flag;
pub enum MicrocodeStep {
ReadRegisterA,
ReadRegisterX,
ReadRegisterY,
ReadFlag(Mos6502Flag),
WriteRegisterA,
WriteRegisterX,
WriteRegisterY,
WriteFlag(Mos6502Flag, bool),
ReadMemory(u16),
WriteMemory(u16, u8),
ALUAdd(u8, u8),
ALUSub(u8, u8),
ALUAddC(u8, u8, bool),
ALUSubC(u8, u8, bool),
}
-3
View File
@@ -1,3 +0,0 @@
pub mod encode;
pub mod decoder;
pub mod microcode_steps;
+4 -1
View File
@@ -2,5 +2,8 @@ pub mod address_mode;
pub mod mos6502cpu;
pub mod instruction;
pub mod mos6502flags;
pub mod isa;
pub mod constants;
mod operation;
mod op_info;
mod operand;
mod instruction_table;
+10
View File
@@ -0,0 +1,10 @@
use crate::address_mode::AddressMode;
use crate::operation::Operation;
#[derive(Debug, Copy, Clone)]
pub struct OpInfo {
pub operation: Operation,
pub mode: AddressMode,
pub length: u8,
pub cycles: u8,
}
+6
View File
@@ -0,0 +1,6 @@
#[derive(Debug, PartialEq)]
pub enum Operand {
None,
Byte(u8),
Word(u16),
}
@@ -1,16 +1,6 @@
use crate::address_mode::AddressMode;
use crate::address_mode::AddressMode::*;
use crate::instruction::Instruction::*;
use crate::mos6502flags::Mos6502Flag::*;
mod from_bytes;
mod to_bytes;
mod execute;
mod stub;
mod to_string;
#[derive(PartialEq, Debug)]
pub enum Instruction {
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Operation {
/// ADC Add with Carry
/// A,Z,C,N = A+M+C
///
@@ -35,7 +25,7 @@ pub enum Instruction {
/// Absolute,Y $79 3 4 (+1 if page crossed)
/// (Indirect,X) $61 2 6
/// (Indirect),Y $71 2 5 (+1 if page crossed)
ADC(AddressMode),
ADC,
/// AND
/// A,Z,N = A&M
///
@@ -61,7 +51,7 @@ pub enum Instruction {
/// (Indirect,X) $21 2 6
/// (Indirect),Y $31 2 5 (+1 if page crossed)
///
AND(AddressMode),
AND,
/// ASL
/// A,Z,C,N = M*2 or M,Z,C,N = M*2
///
@@ -83,7 +73,7 @@ pub enum Instruction {
/// ZeroPage,X $16 2 6
/// Absolute $0E 3 6
/// Absolute,X $1E 3 7
ASL(AddressMode),
ASL,
/// BCC Branch if Carry Clear
/// If the carry flag is clear then add the relative displacement to the program counter to cause a branch to a new location.
///
@@ -100,7 +90,8 @@ pub enum Instruction {
/// Relative $90 2 2 (+1 if branch succeeds
///
/// +2 if to a new page)
BCC(AddressMode),
BCC,
/// BCS Branch if Carry Set
/// If the carry flag is set then add the relative displacement to the program counter to cause a branch to a new location.
///
@@ -118,7 +109,8 @@ pub enum Instruction {
/// Relative $B0 2 2 (+1 if branch succeeds
///
/// +2 if to a new page)
BCS(AddressMode),
BCS,
/// BEQ Branch if Equal
/// If the zero flag is set then add the relative displacement to the program counter to cause a branch to a new location.
///
@@ -135,7 +127,7 @@ pub enum Instruction {
/// Relative $F0 2 2 (+1 if branch succeeds
///
/// +2 if to a new page)
BEQ(AddressMode),
BEQ,
/// BIT Bit Test
/// A & M, N = M7, V = M6
///
@@ -153,7 +145,7 @@ pub enum Instruction {
/// Addressing Mode Opcode Bytes Cycles
/// ZeroPage $24 2 3
/// Absolute $2C 3 4
BIT(AddressMode),
BIT,
/// BMI Branch if Minus
/// If the negative flag is set then add the relative displacement to the program counter to cause a branch to a new location.
///
@@ -170,7 +162,7 @@ pub enum Instruction {
/// Relative $30 2 2 (+1 if branch succeeds
///
/// +2 if to a new page)
BMI(AddressMode),
BMI,
/// BNE Branch if Not Equal
/// If the zero flag is clear then add the relative displacement to the program counter to cause a branch to a new location.
///
@@ -187,7 +179,7 @@ pub enum Instruction {
/// Relative $D0 2 2 (+1 if branch succeeds
///
/// +2 if to a new page)
BNE(AddressMode),
BNE,
/// BPL Branch if Positive
/// If the negative flag is clear then add the relative displacement to the program counter to cause a branch to a new location.
///
@@ -204,7 +196,7 @@ pub enum Instruction {
/// Relative $10 2 2 (+1 if branch succeeds
///
/// +2 if to a new page)
BPL(AddressMode),
BPL,
/// BRK Force Interrupt
/// The BRK instruction forces the generation of an interrupt request. The program counter and processor status are pushed on the stack then the IRQ interrupt vector at $FFFE/F is loaded into the PC and the break flag in the status set to one.
///
@@ -235,7 +227,7 @@ pub enum Instruction {
/// Relative $50 2 2 (+1 if branch succeeds
///
/// +2 if to a new page)
BVC(AddressMode),
BVC,
/// BVS Branch if Overflow Set
/// If the overflow flag is set then add the relative displacement to the program counter to cause a branch to a new location.
///
@@ -252,7 +244,7 @@ pub enum Instruction {
/// Relative $70 2 2 (+1 if branch succeeds
///
/// +2 if to a new page)
BVS(AddressMode),
BVS,
/// CLC Clear Carry Flag
/// C = 0
///
@@ -337,7 +329,7 @@ pub enum Instruction {
/// Absolute,Y $D9 3 4 (+1 if page crossed)
/// (Indirect,X) $C1 2 6
/// (Indirect),Y $D1 2 5 (+1 if page crossed)
CMP(AddressMode),
CMP,
/// CPX Compare X Register
/// Z,C,N = X-M
///
@@ -356,7 +348,7 @@ pub enum Instruction {
/// Immediate $E0 2 2
/// Zero Page $E4 2 3
/// Absolute $EC 3 4
CPX(AddressMode),
CPX,
/// CPY Compare Y Register
/// Z,C,N = Y-M
///
@@ -375,7 +367,7 @@ pub enum Instruction {
/// Immediate $C0 2 2
/// Zero Page $C4 2 3
/// Absolute $CC 3 4
CPY(AddressMode),
CPY,
/// DEC Decrement Memory
/// M,Z,N = M-1
///
@@ -395,7 +387,7 @@ pub enum Instruction {
/// Zero Page,X $D6 2 6
/// Absolute $CE 3 6
/// Absolute,X $DE 3 7
DEC(AddressMode),
DEC,
/// DEX Decrement X Register
/// X,Z,N = X-1
///
@@ -453,7 +445,7 @@ pub enum Instruction {
/// Absolute,Y $59 3 4 (+1 if page crossed)
/// (Indirect,X) $41 2 6
/// (Indirect),Y $51 2 5 (+1 if page crossed)
EOR(AddressMode),
EOR,
/// INC Increment Memory
/// M,Z,N = M+1
///
@@ -473,7 +465,7 @@ pub enum Instruction {
/// Zero Page,X $F6 2 6
/// Absolute $EE 3 6
/// Absolute,X $FE 3 7
INC(AddressMode),
INC,
/// INX Increment X Register
/// X,Z,N = X+1
///
@@ -523,7 +515,7 @@ pub enum Instruction {
/// Addressing Mode Opcode Bytes Cycles
/// Absolute $4C 3 3
/// Indirect $6C 3 5
JMP(AddressMode),
JMP,
/// JSR Jump to Subroutine
/// The JSR instruction pushes the address (minus one) of the return point on to the stack and then sets the program counter to the target memory address.
///
@@ -538,7 +530,7 @@ pub enum Instruction {
/// N Negative Flag Not affected
/// Addressing Mode Opcode Bytes Cycles
/// Absolute $20 3 6
JSR(AddressMode),
JSR,
/// LDA Load Accumulator
/// A,Z,N = M
///
@@ -560,7 +552,7 @@ pub enum Instruction {
/// Absolute,Y $B9 3 4 (+1 if page crossed)
/// (Indirect,X) $A1 2 6
/// (Indirect),Y $B1 2 5 (+1 if page crossed)
LDA(AddressMode),
LDA,
/// LDX Load X Register
/// X,Z,N = M
///
@@ -579,7 +571,7 @@ pub enum Instruction {
/// Zero Page,Y $B6 2 4
/// Absolute $AE 3 4
/// Absolute,Y $BE 3 4 (+1 if page crossed)
LDX(AddressMode),
LDX,
/// LDY Load Y Register
/// Y,Z,N = M
///
@@ -598,7 +590,7 @@ pub enum Instruction {
/// Zero Page,X $B4 2 4
/// Absolute $AC 3 4
/// Absolute,X $BC 3 4 (+1 if page crossed)
LDY(AddressMode),
LDY,
/// LSR Logical Shift Right
/// A,C,Z,N = A/2 or M,C,Z,N = M/2
///
@@ -619,7 +611,7 @@ pub enum Instruction {
/// ZeroPage,X $56 2 6
/// Absolute $4E 3 6
/// Absolute,X $5E 3 7
LSR(AddressMode),
LSR,
/// NOP No Operation
/// The NOP instruction causes no changes to the processor other than the normal incrementing of the program counter to the next instruction.
///
@@ -658,7 +650,7 @@ pub enum Instruction {
/// Absolute,Y $19 3 4 (+1 if page crossed)
/// (Indirect,X) $01 2 6
/// (Indirect),Y $11 2 5 (+1 if page crossed)
ORA(AddressMode),
ORA,
/// PHA Push Accumulator
/// Pushes a copy of the accumulator on to the stack.
///
@@ -735,7 +727,7 @@ pub enum Instruction {
/// ZeroPage,X $36 2 6
/// Absolute $2E 3 6
/// Absolute,X $3E 3 7
ROL(AddressMode),
ROL,
/// ROR Rotate Right
/// Move each of the bits in either A or M one place to the right. Bit 7 is filled with the current value of the carry flag while the old bit 0 becomes the new carry flag value.
///
@@ -754,7 +746,7 @@ pub enum Instruction {
/// ZeroPage,X $76 2 6
/// Absolute $6E 3 6
/// Absolute,X $7E 3 7
ROR(AddressMode),
ROR,
/// RTI Return from Interrupt
/// The RTI instruction is used at the end of an interrupt processing routine. It pulls the processor flags from the stack followed by the program counter.
///
@@ -808,7 +800,7 @@ pub enum Instruction {
/// Absolute,Y $F9 3 4 (+1 if page crossed)
/// (Indirect,X) $E1 2 6
/// (Indirect),Y $F1 2 5 (+1 if page crossed)
SBC(AddressMode),
SBC,
/// SEC Set Carry Flag
/// C = 1
///
@@ -876,7 +868,7 @@ pub enum Instruction {
/// Absolute,Y $99 3 5
/// (Indirect,X) $81 2 6
/// (Indirect),Y $91 2 6
STA(AddressMode),
STA,
/// STX Store X Register
/// M = X
///
@@ -895,7 +887,7 @@ pub enum Instruction {
/// Zero Page $86 2 3
/// Zero Page,Y $96 2 4
/// Absolute $8E 3 4
STX(AddressMode),
STX,
/// STY Store Y Register
/// M = Y
///
@@ -914,7 +906,7 @@ pub enum Instruction {
/// Zero Page $84 2 3
/// Zero Page,X $94 2 4
/// Absolute $8C 3 4
STY(AddressMode),
STY,
/// TAX Transfer Accumulator to X
/// X = A
///
@@ -1018,199 +1010,3 @@ pub enum Instruction {
/// Implied $98 1 2
TYA,
}
#[cfg(test)]
mod test {
use crate::address_mode::AddressMode::*;
use crate::instruction::Instruction::*;
use super::*;
#[test]
fn to_string_to_bytes_from_bytes() {
let params = vec![
(ADC(Immediate(0x01)), "ADC #$01", vec![0x69, 0x01]),
(ADC(ZeroPage(0x01)), "ADC $01", vec![0x65, 0x01]),
(ADC(ZeroPageX(0x01)), "ADC $01,X", vec![0x75, 0x01]),
(ADC(Absolute(0xabcd)), "ADC $abcd", vec![0x6d, 0xcd, 0xab]),
(ADC(AbsoluteX(0xabcd)), "ADC $abcd,X", vec![0x7d, 0xcd, 0xab]),
(ADC(AbsoluteY(0xabcd)), "ADC $abcd,Y", vec![0x79, 0xcd, 0xab]),
(ADC(IndirectX(0xab)), "ADC ($ab,X)", vec![0x61, 0xab]),
(ADC(IndirectY(0xab)), "ADC ($ab),Y", vec![0x71, 0xab]),
(AND(Immediate(0x01)), "AND #$01", vec![0x29, 0x01]),
(AND(ZeroPage(0x01)), "AND $01", vec![0x25, 0x01]),
(AND(ZeroPageX(0x01)), "AND $01,X", vec![0x35, 0x01]),
(AND(Absolute(0xabcd)), "AND $abcd", vec![0x2d, 0xcd, 0xab]),
(AND(AbsoluteX(0xabcd)), "AND $abcd,X", vec![0x3d, 0xcd, 0xab]),
(AND(AbsoluteY(0xabcd)), "AND $abcd,Y", vec![0x39, 0xcd, 0xab]),
(AND(IndirectX(0xab)), "AND ($ab,X)", vec![0x21, 0xab]),
(AND(IndirectY(0xab)), "AND ($ab),Y", vec![0x31, 0xab]),
(ASL(Accumulator), "ASL A", vec![0x0a]),
(ASL(ZeroPage(0xab)), "ASL $ab", vec![0x06, 0xab]),
(ASL(ZeroPageX(0xab)), "ASL $ab,X", vec![0x16, 0xab]),
(ASL(Absolute(0xabcd)), "ASL $abcd", vec![0x0e, 0xcd, 0xab]),
(ASL(AbsoluteX(0xabcd)), "ASL $abcd,X", vec![0x1e, 0xcd, 0xab]),
(BCC(Immediate(0xab)), "BCC #$ab", vec![0x90, 0xab]),
(BCS(Immediate(0xab)), "BCS #$ab", vec![0xb0, 0xab]),
(BEQ(Immediate(0xab)), "BEQ #$ab", vec![0xf0, 0xab]),
(BIT(ZeroPage(0xab)), "BIT $ab", vec![0x24, 0xab]),
(BIT(Absolute(0xabcd)), "BIT $abcd", vec![0x2c, 0xcd, 0xab]),
(BMI(Immediate(0xab)), "BMI #$ab", vec![0x30, 0xab]),
(BNE(Immediate(0xab)), "BNE #$ab", vec![0xd0, 0xab]),
(BPL(Immediate(0xab)), "BPL #$ab", vec![0x10, 0xab]),
(BVC(Immediate(0xab)), "BVC #$ab", vec![0x50, 0xab]),
(BVS(Immediate(0xab)), "BVS #$ab", vec![0x70, 0xab]),
(CLC, "CLC", vec![0x18]),
(CLD, "CLD", vec![0xd8]),
(CLV, "CLV", vec![0x8b]),
(CLI, "CLI", vec![0x85]),
(CMP(Immediate(0xab)), "CMP #$ab", vec![0xc9, 0xab]),
(CMP(ZeroPage(0xab)), "CMP $ab", vec![0xc5, 0xab]),
(CMP(ZeroPageX(0xab)), "CMP $ab,X", vec![0xd5, 0xab]),
(CMP(Absolute(0xabcd)), "CMP $abcd", vec![0xcd, 0xcd, 0xab]),
(CMP(AbsoluteX(0xabcd)), "CMP $abcd,X", vec![0xdd, 0xcd, 0xab]),
(CMP(IndirectX(0xab)), "CMP ($ab,X)", vec![0xc1, 0xab]),
(CMP(IndirectY(0xab)), "CMP ($ab),Y", vec![0xd1, 0xab]),
(CPX(Immediate(0xab)), "CPX #$ab", vec![0xe0, 0xab]),
(CPX(ZeroPage(0xab)), "CPX $ab", vec![0xe4, 0xab]),
(CPX(Absolute(0xabcd)), "CPX $abcd", vec![0xec, 0xcd, 0xab]),
(CPY(Immediate(0xab)), "CPY #$ab", vec![0xc0, 0xab]),
(CPY(Immediate(0xab)), "CPY #$ab", vec![0xc0, 0xab]),
(CPY(ZeroPage(0xab)), "CPY $ab", vec![0xc4, 0xab]),
(CPY(Absolute(0xabcd)), "CPY $abcd", vec![0xcc, 0xcd, 0xab]),
(DEC(ZeroPage(0xab)), "DEC $ab", vec![0xc6, 0xab]),
(DEC(ZeroPageX(0xab)), "DEC $ab,X", vec![0xd6, 0xab]),
(DEC(Absolute(0xabcd)), "DEC $abcd", vec![0xce, 0xcd, 0xab]),
// (DEC(AbsoluteX(0xabcd)), "DEC $abcd,X", vec![0xde, 0xcd, 0xab]),
(DEX, "DEX", vec![0xca]),
(DEY, "DEY", vec![0x88]),
(EOR(Immediate(0xab)), "EOR #$ab", vec![0x49, 0xab]),
(EOR(ZeroPage(0xab)), "EOR $ab", vec![0x45, 0xab]),
(EOR(ZeroPageX(0xab)), "EOR $ab,X", vec![0x55, 0xab]),
(EOR(Absolute(0xabcd)), "EOR $abcd", vec![0x4d, 0xcd, 0xab]),
(EOR(AbsoluteX(0xabcd)), "EOR $abcd,X", vec![0x5d, 0xcd, 0xab]),
(EOR(IndirectX(0xab)), "EOR ($ab,X)", vec![0x41, 0xab]),
(EOR(IndirectY(0xab)), "EOR ($ab),Y", vec![0x51, 0xab]),
(INC(ZeroPage(0xab)), "INC $ab", vec![0xe6, 0xab]),
(INC(ZeroPageX(0xab)), "INC $ab,X", vec![0xf6, 0xab]),
(INC(Absolute(0xabcd)), "INC $abcd", vec![0xee, 0xcd, 0xab]),
(INC(AbsoluteX(0xabcd)), "INC $abcd,X", vec![0xfe, 0xcd, 0xab]),
(INX, "INX", vec![0xe8]),
(INY, "INY", vec![0xc8]),
(JMP(Absolute(0xabcd)), "JMP $abcd", vec![0x4c, 0xcd, 0xab]),
(JMP(IndirectX(0xab)), "JMP ($ab,X)", vec![0x6c, 0xab]),
(JSR(Immediate(0xab)), "JSR #$ab", vec![0x20, 0xab]),
(LDA(Immediate(0xab)), "LDA #$ab", vec![0xa9, 0xab]),
(LDA(ZeroPage(0xab)), "LDA $ab", vec![0xa5, 0xab]),
(LDA(ZeroPageX(0xab)), "LDA $ab,X", vec![0xb5, 0xab]),
(LDA(Absolute(0xabcd)), "LDA $abcd", vec![0xad, 0xcd, 0xab]),
(LDA(AbsoluteX(0xabcd)), "LDA $abcd,X", vec![0xbd, 0xcd, 0xab]),
(LDA(AbsoluteY(0xabcd)), "LDA $abcd,Y", vec![0xb9, 0xcd, 0xab]),
(LDA(IndirectX(0xab)), "LDA ($ab,X)", vec![0xa1, 0xab]),
(LDA(IndirectY(0xab)), "LDA ($ab),Y", vec![0xb1, 0xab]),
(LDX(Immediate(0xab)), "LDX #$ab", vec![0xa2, 0xab]),
(LDX(ZeroPage(0xab)), "LDX $ab", vec![0xa6, 0xab]),
(LDX(ZeroPageY(0xab)), "LDX $ab,Y", vec![0x86, 0xab]),
(LDX(Absolute(0xabcd)), "LDX $abcd", vec![0xae, 0xcd, 0xab]),
(LDX(AbsoluteY(0xabcd)), "LDX $abcd,Y", vec![0xbe, 0xcd, 0xab]),
(LDY(Immediate(0xab)), "LDY #$ab", vec![0xa0, 0xab]),
(LDY(ZeroPage(0xab)), "LDY $ab", vec![0xa4, 0xab]),
(LDY(ZeroPageX(0xab)), "LDY $ab,X", vec![0x84, 0xab]),
(LDY(Absolute(0xabcd)), "LDY $abcd", vec![0xac, 0xcd, 0xab]),
(LDY(AbsoluteX(0xabcd)), "LDY $abcd,X", vec![0xbc, 0xcd, 0xab]),
(LSR(Accumulator), "LSR A", vec![0x4a]),
(LSR(ZeroPage(0xab)), "LSR $ab", vec![0x46, 0xab]),
(LSR(ZeroPageX(0xab)), "LSR $ab,X", vec![0x56, 0xab]),
(LSR(Absolute(0xabcd)), "LSR $abcd", vec![0x4e, 0xcd, 0xab]),
(LSR(AbsoluteX(0xabcd)), "LSR $abcd,X", vec![0x5e, 0xcd, 0xab]),
// Nop nop nop.
(NOP, "NOP", vec![0xea]),
(ORA(Immediate(0xab)), "ORA #$ab", vec![0x09, 0xab]),
(ORA(ZeroPage(0xab)), "ORA $ab", vec![0x05, 0xab]),
(ORA(ZeroPageX(0xab)), "ORA $ab,X", vec![0x15, 0xab]),
(ORA(Absolute(0xabcd)), "ORA $abcd", vec![0x0d, 0xcd, 0xab]),
(ORA(AbsoluteX(0xabcd)), "ORA $abcd,X", vec![0x1d, 0xcd, 0xab]),
(ORA(AbsoluteY(0xabcd)), "ORA $abcd,Y", vec![0x19, 0xcd, 0xab]),
(ORA(IndirectX(0xab)), "ORA ($ab,X)", vec![0x01, 0xab]),
(ORA(IndirectY(0xab)), "ORA ($ab),Y", vec![0x11, 0xab]),
(PHA, "PHA", vec![0x48]),
(PHP, "PHP", vec![0x08]),
(PLA, "PLA", vec![0x68]),
(PLP, "PLP", vec![0x28]),
(ROL(Accumulator), "ROL A", vec![0x2a]),
(ROL(ZeroPage(0xab)), "ROL $ab", vec![0x26, 0xab]),
(ROL(ZeroPageX(0xab)), "ROL $ab,X", vec![0x36, 0xab]),
(ROL(Absolute(0xabcd)), "ROL $abcd", vec![0x2e, 0xcd, 0xab]),
(ROL(AbsoluteX(0xabcd)), "ROL $abcd,X", vec![0x3e, 0xcd, 0xab]),
(ROR(Accumulator), "ROR A", vec![0x6a]),
(ROR(ZeroPage(0xab)), "ROR $ab", vec![0x66, 0xab]),
(ROR(ZeroPageX(0xab)), "ROR $ab,X", vec![0x76, 0xab]),
(ROR(Absolute(0xabcd)), "ROR $abcd", vec![0x6e, 0xcd, 0xab]),
(ROR(AbsoluteX(0xabcd)), "ROR $abcd,X", vec![0x7e, 0xcd, 0xab]),
(RTI, "RTI", vec![0x40]),
(RTS, "RTS", vec![0x60]),
(SBC(Immediate(0xab)), "SBC #$ab", vec![0xe9, 0xcd, 0xab]),
(SBC(ZeroPage(0xab)), "SBC $ab", vec![0xe5, 0xab]),
(SBC(ZeroPageX(0xab)), "SBC $ab,X", vec![0xf5, 0xab]),
(SBC(Absolute(0xabcd)), "SBC $abcd", vec![0xed, 0xcd, 0xab]),
(SBC(AbsoluteX(0xabcd)), "SBC $abcd,X", vec![0xfd, 0xcd, 0xab]),
(SBC(AbsoluteY(0xabcd)), "SBC $abcd,Y", vec![0xf9, 0xcd, 0xab]),
(SBC(IndirectX(0xab)), "SBC ($ab,X)", vec![0xe1, 0xab]),
(SBC(IndirectY(0xab)), "SBC ($ab),Y", vec![0xf1, 0xab]),
(SEC, "SEC", vec![0x38]),
(SED, "SED", vec![0xf8]),
(SEI, "SEI", vec![0x78]),
(STA(ZeroPage(0xab)), "STA $ab", vec![0x85, 0xab]),
(STA(ZeroPageX(0xab)), "STA $ab,X", vec![0x95, 0xab]),
(STA(Absolute(0xabcd)), "STA $abcd", vec![0x8d, 0xcd, 0xab]),
(STA(AbsoluteX(0xabcd)), "STA $abcd,X", vec![0x9d, 0xcd, 0xab]),
(STA(AbsoluteY(0xabcd)), "STA $abcd,Y", vec![0x99, 0xcd, 0xab]),
(STA(IndirectX(0xab)), "STA ($ab,X)", vec![0x81, 0xab]),
(STA(IndirectY(0xab)), "STA ($ab),Y", vec![0x91, 0xab]),
(STX(ZeroPage(0xab)), "STX $ab", vec![0x86, 0xab]),
(STX(ZeroPageX(0xab)), "STX $ab,X", vec![0x96, 0xab]),
(STX(Absolute(0xabcd)), "STX $abcd", vec![0x8e, 0xcd, 0xab]),
(STY(ZeroPage(0xab)), "STY $ab", vec![0x84, 0xab]),
(STY(ZeroPageX(0xab)), "STY $ab,X", vec![0x94, 0xab]),
(STY(Absolute(0xabcd)), "STY $abcd", vec![0x8c, 0xcd, 0xab]),
(TAX, "TAX", vec![0xaa]),
(TAY, "TAY", vec![0xa8]),
(TSX, "TSX", vec![0xba]),
(TXA, "TXA", vec![0x8a]),
(TXS, "TXS", vec![0x9a]),
(TYA, "TYA", vec![0x98])
];
for (instruction, string, bytes) in params {
println!("COMPARE OF [{:?}] to {:?} and [{}]", instruction, bytes, string);
// from instruction to string
assert_eq!(
instruction.to_string(),
string
);
print!("to string passed.");
/*
// from instruction to bytes
assert_eq!(
instruction.to_bytes(),
bytes
);
print!("to bytes passed.");
// from bytes to instruction
assert_eq!(
instruction,
Instruction::from_bytes(bytes)
);
println!("from bytes passed.");
*/
}
}
}