applies chatgpt suggestions.
... does not appear to decode everything
This commit is contained in:
@@ -1,11 +1,10 @@
|
|||||||
use core::instruction::Instruction;
|
use core::instruction::Instruction;
|
||||||
use core::address_mode::AddressMode;
|
use core::address_mode::AddressMode;
|
||||||
use core::isa::decoder::Decoder;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Taxation is Theft");
|
println!("Taxation is Theft");
|
||||||
|
|
||||||
Decoder::decode(vec![0b11100011]);
|
Instruction::from_bytes(vec![0b11100011]);
|
||||||
|
|
||||||
let instruction = Instruction::ADC(AddressMode::Immediate(0x45));
|
let instruction = Instruction::ADC(AddressMode::Immediate(0x45));
|
||||||
println!("Instruction = {:?}", instruction.to_string());
|
println!("Instruction = {:?}", instruction.to_string());
|
||||||
|
|||||||
+1
-1
@@ -3,4 +3,4 @@ name = "core"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4.26"
|
log = "0.4"
|
||||||
+16
-10
@@ -1,17 +1,23 @@
|
|||||||
|
use std::fmt::{Display, Formatter};
|
||||||
use std::ops::Add;
|
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::mos6502cpu::Mos6502Cpu;
|
||||||
|
use crate::operation::Operation;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||||
pub enum AddressMode {
|
pub enum AddressMode {
|
||||||
Implied,
|
Implied,
|
||||||
Accumulator,
|
Accumulator,
|
||||||
Immediate(u8),
|
Immediate,
|
||||||
ZeroPage(u8),
|
ZeroPage,
|
||||||
ZeroPageX(u8),
|
ZeroPageX,
|
||||||
ZeroPageY(u8),
|
ZeroPageY,
|
||||||
Absolute(u16),
|
Absolute,
|
||||||
AbsoluteX(u16),
|
AbsoluteX,
|
||||||
AbsoluteY(u16),
|
AbsoluteY,
|
||||||
IndirectX(u8),
|
Indirect,
|
||||||
IndirectY(u8),
|
IndirectX,
|
||||||
|
IndirectY,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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_ZPX: u8 = 0xd5;
|
||||||
pub const ISA_OP_CMP_ABS: u8 = 0xcd;
|
pub const ISA_OP_CMP_ABS: u8 = 0xcd;
|
||||||
pub const ISA_OP_CMP_ABSX: u8 = 0xdd;
|
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_INDX: u8 = 0xc1;
|
||||||
pub const ISA_OP_CMP_INDY: u8 = 0xd1;
|
pub const ISA_OP_CMP_INDY: u8 = 0xd1;
|
||||||
pub const ISA_OP_CPX_I: u8 = 0xe0;
|
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_INDX: u8 = 0x81;
|
||||||
pub const ISA_OP_STA_INDY: u8 = 0x91;
|
pub const ISA_OP_STA_INDY: u8 = 0x91;
|
||||||
pub const ISA_OP_STX_ZP: u8 = 0x86;
|
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_STX_ABS: u8 = 0x8e;
|
||||||
pub const ISA_OP_STY_ZP: u8 = 0x84;
|
pub const ISA_OP_STY_ZP: u8 = 0x84;
|
||||||
pub const ISA_OP_STY_ZPX: u8 = 0x94;
|
pub const ISA_OP_STY_ZPX: u8 = 0x94;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 => {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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![] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
};
|
||||||
@@ -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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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());
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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),
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
pub mod encode;
|
|
||||||
pub mod decoder;
|
|
||||||
pub mod microcode_steps;
|
|
||||||
+4
-1
@@ -2,5 +2,8 @@ pub mod address_mode;
|
|||||||
pub mod mos6502cpu;
|
pub mod mos6502cpu;
|
||||||
pub mod instruction;
|
pub mod instruction;
|
||||||
pub mod mos6502flags;
|
pub mod mos6502flags;
|
||||||
pub mod isa;
|
|
||||||
pub mod constants;
|
pub mod constants;
|
||||||
|
mod operation;
|
||||||
|
mod op_info;
|
||||||
|
mod operand;
|
||||||
|
mod instruction_table;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
}
|
||||||
@@ -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;
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
mod to_bytes;
|
pub enum Operation {
|
||||||
mod execute;
|
|
||||||
mod stub;
|
|
||||||
mod to_string;
|
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
|
||||||
pub enum Instruction {
|
|
||||||
/// ADC – Add with Carry
|
/// ADC – Add with Carry
|
||||||
/// A,Z,C,N = A+M+C
|
/// A,Z,C,N = A+M+C
|
||||||
///
|
///
|
||||||
@@ -35,7 +25,7 @@ pub enum Instruction {
|
|||||||
/// Absolute,Y $79 3 4 (+1 if page crossed)
|
/// Absolute,Y $79 3 4 (+1 if page crossed)
|
||||||
/// (Indirect,X) $61 2 6
|
/// (Indirect,X) $61 2 6
|
||||||
/// (Indirect),Y $71 2 5 (+1 if page crossed)
|
/// (Indirect),Y $71 2 5 (+1 if page crossed)
|
||||||
ADC(AddressMode),
|
ADC,
|
||||||
/// AND
|
/// AND
|
||||||
/// A,Z,N = A&M
|
/// A,Z,N = A&M
|
||||||
///
|
///
|
||||||
@@ -61,7 +51,7 @@ pub enum Instruction {
|
|||||||
/// (Indirect,X) $21 2 6
|
/// (Indirect,X) $21 2 6
|
||||||
/// (Indirect),Y $31 2 5 (+1 if page crossed)
|
/// (Indirect),Y $31 2 5 (+1 if page crossed)
|
||||||
///
|
///
|
||||||
AND(AddressMode),
|
AND,
|
||||||
/// ASL
|
/// ASL
|
||||||
/// A,Z,C,N = M*2 or M,Z,C,N = M*2
|
/// 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
|
/// ZeroPage,X $16 2 6
|
||||||
/// Absolute $0E 3 6
|
/// Absolute $0E 3 6
|
||||||
/// Absolute,X $1E 3 7
|
/// Absolute,X $1E 3 7
|
||||||
ASL(AddressMode),
|
ASL,
|
||||||
/// BCC – Branch if Carry Clear
|
/// 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.
|
/// 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
|
/// Relative $90 2 2 (+1 if branch succeeds
|
||||||
///
|
///
|
||||||
/// +2 if to a new page)
|
/// +2 if to a new page)
|
||||||
BCC(AddressMode),
|
|
||||||
|
BCC,
|
||||||
/// BCS – Branch if Carry Set
|
/// 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.
|
/// 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
|
/// Relative $B0 2 2 (+1 if branch succeeds
|
||||||
///
|
///
|
||||||
/// +2 if to a new page)
|
/// +2 if to a new page)
|
||||||
BCS(AddressMode),
|
|
||||||
|
BCS,
|
||||||
/// BEQ – Branch if Equal
|
/// 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.
|
/// 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
|
/// Relative $F0 2 2 (+1 if branch succeeds
|
||||||
///
|
///
|
||||||
/// +2 if to a new page)
|
/// +2 if to a new page)
|
||||||
BEQ(AddressMode),
|
BEQ,
|
||||||
/// BIT – Bit Test
|
/// BIT – Bit Test
|
||||||
/// A & M, N = M7, V = M6
|
/// A & M, N = M7, V = M6
|
||||||
///
|
///
|
||||||
@@ -153,7 +145,7 @@ pub enum Instruction {
|
|||||||
/// Addressing Mode Opcode Bytes Cycles
|
/// Addressing Mode Opcode Bytes Cycles
|
||||||
/// ZeroPage $24 2 3
|
/// ZeroPage $24 2 3
|
||||||
/// Absolute $2C 3 4
|
/// Absolute $2C 3 4
|
||||||
BIT(AddressMode),
|
BIT,
|
||||||
/// BMI – Branch if Minus
|
/// 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.
|
/// 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
|
/// Relative $30 2 2 (+1 if branch succeeds
|
||||||
///
|
///
|
||||||
/// +2 if to a new page)
|
/// +2 if to a new page)
|
||||||
BMI(AddressMode),
|
BMI,
|
||||||
/// BNE – Branch if Not Equal
|
/// 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.
|
/// 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
|
/// Relative $D0 2 2 (+1 if branch succeeds
|
||||||
///
|
///
|
||||||
/// +2 if to a new page)
|
/// +2 if to a new page)
|
||||||
BNE(AddressMode),
|
BNE,
|
||||||
/// BPL – Branch if Positive
|
/// 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.
|
/// 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
|
/// Relative $10 2 2 (+1 if branch succeeds
|
||||||
///
|
///
|
||||||
/// +2 if to a new page)
|
/// +2 if to a new page)
|
||||||
BPL(AddressMode),
|
BPL,
|
||||||
/// BRK – Force Interrupt
|
/// 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.
|
/// 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
|
/// Relative $50 2 2 (+1 if branch succeeds
|
||||||
///
|
///
|
||||||
/// +2 if to a new page)
|
/// +2 if to a new page)
|
||||||
BVC(AddressMode),
|
BVC,
|
||||||
/// BVS – Branch if Overflow Set
|
/// 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.
|
/// 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
|
/// Relative $70 2 2 (+1 if branch succeeds
|
||||||
///
|
///
|
||||||
/// +2 if to a new page)
|
/// +2 if to a new page)
|
||||||
BVS(AddressMode),
|
BVS,
|
||||||
/// CLC – Clear Carry Flag
|
/// CLC – Clear Carry Flag
|
||||||
/// C = 0
|
/// C = 0
|
||||||
///
|
///
|
||||||
@@ -337,7 +329,7 @@ pub enum Instruction {
|
|||||||
/// Absolute,Y $D9 3 4 (+1 if page crossed)
|
/// Absolute,Y $D9 3 4 (+1 if page crossed)
|
||||||
/// (Indirect,X) $C1 2 6
|
/// (Indirect,X) $C1 2 6
|
||||||
/// (Indirect),Y $D1 2 5 (+1 if page crossed)
|
/// (Indirect),Y $D1 2 5 (+1 if page crossed)
|
||||||
CMP(AddressMode),
|
CMP,
|
||||||
/// CPX – Compare X Register
|
/// CPX – Compare X Register
|
||||||
/// Z,C,N = X-M
|
/// Z,C,N = X-M
|
||||||
///
|
///
|
||||||
@@ -356,7 +348,7 @@ pub enum Instruction {
|
|||||||
/// Immediate $E0 2 2
|
/// Immediate $E0 2 2
|
||||||
/// Zero Page $E4 2 3
|
/// Zero Page $E4 2 3
|
||||||
/// Absolute $EC 3 4
|
/// Absolute $EC 3 4
|
||||||
CPX(AddressMode),
|
CPX,
|
||||||
/// CPY – Compare Y Register
|
/// CPY – Compare Y Register
|
||||||
/// Z,C,N = Y-M
|
/// Z,C,N = Y-M
|
||||||
///
|
///
|
||||||
@@ -375,7 +367,7 @@ pub enum Instruction {
|
|||||||
/// Immediate $C0 2 2
|
/// Immediate $C0 2 2
|
||||||
/// Zero Page $C4 2 3
|
/// Zero Page $C4 2 3
|
||||||
/// Absolute $CC 3 4
|
/// Absolute $CC 3 4
|
||||||
CPY(AddressMode),
|
CPY,
|
||||||
/// DEC – Decrement Memory
|
/// DEC – Decrement Memory
|
||||||
/// M,Z,N = M-1
|
/// M,Z,N = M-1
|
||||||
///
|
///
|
||||||
@@ -395,7 +387,7 @@ pub enum Instruction {
|
|||||||
/// Zero Page,X $D6 2 6
|
/// Zero Page,X $D6 2 6
|
||||||
/// Absolute $CE 3 6
|
/// Absolute $CE 3 6
|
||||||
/// Absolute,X $DE 3 7
|
/// Absolute,X $DE 3 7
|
||||||
DEC(AddressMode),
|
DEC,
|
||||||
/// DEX – Decrement X Register
|
/// DEX – Decrement X Register
|
||||||
/// X,Z,N = X-1
|
/// X,Z,N = X-1
|
||||||
///
|
///
|
||||||
@@ -453,7 +445,7 @@ pub enum Instruction {
|
|||||||
/// Absolute,Y $59 3 4 (+1 if page crossed)
|
/// Absolute,Y $59 3 4 (+1 if page crossed)
|
||||||
/// (Indirect,X) $41 2 6
|
/// (Indirect,X) $41 2 6
|
||||||
/// (Indirect),Y $51 2 5 (+1 if page crossed)
|
/// (Indirect),Y $51 2 5 (+1 if page crossed)
|
||||||
EOR(AddressMode),
|
EOR,
|
||||||
/// INC – Increment Memory
|
/// INC – Increment Memory
|
||||||
/// M,Z,N = M+1
|
/// M,Z,N = M+1
|
||||||
///
|
///
|
||||||
@@ -473,7 +465,7 @@ pub enum Instruction {
|
|||||||
/// Zero Page,X $F6 2 6
|
/// Zero Page,X $F6 2 6
|
||||||
/// Absolute $EE 3 6
|
/// Absolute $EE 3 6
|
||||||
/// Absolute,X $FE 3 7
|
/// Absolute,X $FE 3 7
|
||||||
INC(AddressMode),
|
INC,
|
||||||
/// INX – Increment X Register
|
/// INX – Increment X Register
|
||||||
/// X,Z,N = X+1
|
/// X,Z,N = X+1
|
||||||
///
|
///
|
||||||
@@ -523,7 +515,7 @@ pub enum Instruction {
|
|||||||
/// Addressing Mode Opcode Bytes Cycles
|
/// Addressing Mode Opcode Bytes Cycles
|
||||||
/// Absolute $4C 3 3
|
/// Absolute $4C 3 3
|
||||||
/// Indirect $6C 3 5
|
/// Indirect $6C 3 5
|
||||||
JMP(AddressMode),
|
JMP,
|
||||||
/// JSR – Jump to Subroutine
|
/// 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.
|
/// 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
|
/// N Negative Flag Not affected
|
||||||
/// Addressing Mode Opcode Bytes Cycles
|
/// Addressing Mode Opcode Bytes Cycles
|
||||||
/// Absolute $20 3 6
|
/// Absolute $20 3 6
|
||||||
JSR(AddressMode),
|
JSR,
|
||||||
/// LDA – Load Accumulator
|
/// LDA – Load Accumulator
|
||||||
/// A,Z,N = M
|
/// A,Z,N = M
|
||||||
///
|
///
|
||||||
@@ -560,7 +552,7 @@ pub enum Instruction {
|
|||||||
/// Absolute,Y $B9 3 4 (+1 if page crossed)
|
/// Absolute,Y $B9 3 4 (+1 if page crossed)
|
||||||
/// (Indirect,X) $A1 2 6
|
/// (Indirect,X) $A1 2 6
|
||||||
/// (Indirect),Y $B1 2 5 (+1 if page crossed)
|
/// (Indirect),Y $B1 2 5 (+1 if page crossed)
|
||||||
LDA(AddressMode),
|
LDA,
|
||||||
/// LDX – Load X Register
|
/// LDX – Load X Register
|
||||||
/// X,Z,N = M
|
/// X,Z,N = M
|
||||||
///
|
///
|
||||||
@@ -579,7 +571,7 @@ pub enum Instruction {
|
|||||||
/// Zero Page,Y $B6 2 4
|
/// Zero Page,Y $B6 2 4
|
||||||
/// Absolute $AE 3 4
|
/// Absolute $AE 3 4
|
||||||
/// Absolute,Y $BE 3 4 (+1 if page crossed)
|
/// Absolute,Y $BE 3 4 (+1 if page crossed)
|
||||||
LDX(AddressMode),
|
LDX,
|
||||||
/// LDY – Load Y Register
|
/// LDY – Load Y Register
|
||||||
/// Y,Z,N = M
|
/// Y,Z,N = M
|
||||||
///
|
///
|
||||||
@@ -598,7 +590,7 @@ pub enum Instruction {
|
|||||||
/// Zero Page,X $B4 2 4
|
/// Zero Page,X $B4 2 4
|
||||||
/// Absolute $AC 3 4
|
/// Absolute $AC 3 4
|
||||||
/// Absolute,X $BC 3 4 (+1 if page crossed)
|
/// Absolute,X $BC 3 4 (+1 if page crossed)
|
||||||
LDY(AddressMode),
|
LDY,
|
||||||
/// LSR – Logical Shift Right
|
/// LSR – Logical Shift Right
|
||||||
/// A,C,Z,N = A/2 or M,C,Z,N = M/2
|
/// 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
|
/// ZeroPage,X $56 2 6
|
||||||
/// Absolute $4E 3 6
|
/// Absolute $4E 3 6
|
||||||
/// Absolute,X $5E 3 7
|
/// Absolute,X $5E 3 7
|
||||||
LSR(AddressMode),
|
LSR,
|
||||||
/// NOP – No Operation
|
/// 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.
|
/// 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)
|
/// Absolute,Y $19 3 4 (+1 if page crossed)
|
||||||
/// (Indirect,X) $01 2 6
|
/// (Indirect,X) $01 2 6
|
||||||
/// (Indirect),Y $11 2 5 (+1 if page crossed)
|
/// (Indirect),Y $11 2 5 (+1 if page crossed)
|
||||||
ORA(AddressMode),
|
ORA,
|
||||||
/// PHA – Push Accumulator
|
/// PHA – Push Accumulator
|
||||||
/// Pushes a copy of the accumulator on to the stack.
|
/// Pushes a copy of the accumulator on to the stack.
|
||||||
///
|
///
|
||||||
@@ -735,7 +727,7 @@ pub enum Instruction {
|
|||||||
/// ZeroPage,X $36 2 6
|
/// ZeroPage,X $36 2 6
|
||||||
/// Absolute $2E 3 6
|
/// Absolute $2E 3 6
|
||||||
/// Absolute,X $3E 3 7
|
/// Absolute,X $3E 3 7
|
||||||
ROL(AddressMode),
|
ROL,
|
||||||
/// ROR – Rotate Right
|
/// 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.
|
/// 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
|
/// ZeroPage,X $76 2 6
|
||||||
/// Absolute $6E 3 6
|
/// Absolute $6E 3 6
|
||||||
/// Absolute,X $7E 3 7
|
/// Absolute,X $7E 3 7
|
||||||
ROR(AddressMode),
|
ROR,
|
||||||
/// RTI – Return from Interrupt
|
/// 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.
|
/// 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)
|
/// Absolute,Y $F9 3 4 (+1 if page crossed)
|
||||||
/// (Indirect,X) $E1 2 6
|
/// (Indirect,X) $E1 2 6
|
||||||
/// (Indirect),Y $F1 2 5 (+1 if page crossed)
|
/// (Indirect),Y $F1 2 5 (+1 if page crossed)
|
||||||
SBC(AddressMode),
|
SBC,
|
||||||
/// SEC – Set Carry Flag
|
/// SEC – Set Carry Flag
|
||||||
/// C = 1
|
/// C = 1
|
||||||
///
|
///
|
||||||
@@ -876,7 +868,7 @@ pub enum Instruction {
|
|||||||
/// Absolute,Y $99 3 5
|
/// Absolute,Y $99 3 5
|
||||||
/// (Indirect,X) $81 2 6
|
/// (Indirect,X) $81 2 6
|
||||||
/// (Indirect),Y $91 2 6
|
/// (Indirect),Y $91 2 6
|
||||||
STA(AddressMode),
|
STA,
|
||||||
/// STX – Store X Register
|
/// STX – Store X Register
|
||||||
/// M = X
|
/// M = X
|
||||||
///
|
///
|
||||||
@@ -895,7 +887,7 @@ pub enum Instruction {
|
|||||||
/// Zero Page $86 2 3
|
/// Zero Page $86 2 3
|
||||||
/// Zero Page,Y $96 2 4
|
/// Zero Page,Y $96 2 4
|
||||||
/// Absolute $8E 3 4
|
/// Absolute $8E 3 4
|
||||||
STX(AddressMode),
|
STX,
|
||||||
/// STY – Store Y Register
|
/// STY – Store Y Register
|
||||||
/// M = Y
|
/// M = Y
|
||||||
///
|
///
|
||||||
@@ -914,7 +906,7 @@ pub enum Instruction {
|
|||||||
/// Zero Page $84 2 3
|
/// Zero Page $84 2 3
|
||||||
/// Zero Page,X $94 2 4
|
/// Zero Page,X $94 2 4
|
||||||
/// Absolute $8C 3 4
|
/// Absolute $8C 3 4
|
||||||
STY(AddressMode),
|
STY,
|
||||||
/// TAX – Transfer Accumulator to X
|
/// TAX – Transfer Accumulator to X
|
||||||
/// X = A
|
/// X = A
|
||||||
///
|
///
|
||||||
@@ -1018,199 +1010,3 @@ pub enum Instruction {
|
|||||||
/// Implied $98 1 2
|
/// Implied $98 1 2
|
||||||
TYA,
|
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.");
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user