1
0
mirror of https://github.com/mre/mos6502.git synced 2024-11-28 22:51:26 +00:00

Merge pull request #32 from typelist/master

Fix the build for namespaced enums
This commit is contained in:
Johannes Muenzel 2014-11-20 18:36:24 -05:00
commit aa7db5e623
2 changed files with 293 additions and 292 deletions

View File

@ -113,7 +113,7 @@ pub enum Instruction
, TYA // Transfer Y to Accumulator..... | N. ...Z. A = Y
}
pub enum AMOut {
pub enum OpInput {
UseImplied,
UseImmediate(u8),
UseRelative(i8),
@ -149,24 +149,24 @@ fn arr_to_addr(arr: &[u8]) -> Address {
impl AddressingMode {
pub fn extra_bytes(self) -> AddressDiff {
let x = match self {
Accumulator => 0,
Implied => 0,
Immediate => 1,
ZeroPage => 1,
ZeroPageX => 1,
ZeroPageY => 1,
Relative => 1,
Absolute => 2,
AbsoluteX => 2,
AbsoluteY => 2,
Indirect => 2,
IndexedIndirectX => 1,
IndirectIndexedY => 1,
AddressingMode::Accumulator => 0,
AddressingMode::Implied => 0,
AddressingMode::Immediate => 1,
AddressingMode::ZeroPage => 1,
AddressingMode::ZeroPageX => 1,
AddressingMode::ZeroPageY => 1,
AddressingMode::Relative => 1,
AddressingMode::Absolute => 2,
AddressingMode::AbsoluteX => 2,
AddressingMode::AbsoluteY => 2,
AddressingMode::Indirect => 2,
AddressingMode::IndexedIndirectX => 1,
AddressingMode::IndirectIndexedY => 1,
};
AddressDiff(x)
}
pub fn process(self, machine: &Machine, arr: &[u8]) -> AMOut {
pub fn process(self, machine: &Machine, arr: &[u8]) -> OpInput {
debug_assert!({let AddressDiff(x) = self.extra_bytes();
arr.len() == x as uint});
@ -177,60 +177,60 @@ impl AddressingMode {
let memory = &machine.memory;
match self {
Accumulator | Implied => {
AddressingMode::Accumulator | AddressingMode::Implied => {
// Always the same -- no input
UseImplied
OpInput::UseImplied
},
Immediate => {
AddressingMode::Immediate => {
// Use [u8, ..1] specified in instruction as input
UseImmediate(arr[0])
OpInput::UseImmediate(arr[0])
},
ZeroPage => {
AddressingMode::ZeroPage => {
// Use [u8, ..1] from instruction
// Interpret as zero page address
// (Output: an 8-bit zero-page address)
UseAddress(Address(arr[0] as u16))
OpInput::UseAddress(Address(arr[0] as u16))
},
ZeroPageX => {
AddressingMode::ZeroPageX => {
// Use [u8, ..1] from instruction
// Add to X register (as u8 -- the final address is in 0-page)
// (Output: an 8-bit zero-page address)
UseAddress(Address((arr[0] + x) as u16))
OpInput::UseAddress(Address((arr[0] + x) as u16))
},
ZeroPageY => {
AddressingMode::ZeroPageY => {
// Use [u8, ..1] from instruction
// Add to Y register (as u8 -- the final address is in 0-page)
// (Output: an 8-bit zero-page address)
UseAddress(Address((arr[0] + y) as u16))
OpInput::UseAddress(Address((arr[0] + y) as u16))
},
Relative => {
AddressingMode::Relative => {
// Use [u8, ..1] from instruction
// (interpret as relative...)
UseRelative(arr[0] as i8)
OpInput::UseRelative(arr[0] as i8)
},
Absolute => {
AddressingMode::Absolute => {
// Use [u8, ..2] from instruction as address
// (Output: a 16-bit address)
UseAddress(arr_to_addr(arr))
OpInput::UseAddress(arr_to_addr(arr))
},
AbsoluteX => {
AddressingMode::AbsoluteX => {
// Use [u8, ..2] from instruction as address, add X
// (Output: a 16-bit address)
UseAddress(arr_to_addr(arr) + AddressDiff(x as i32))
OpInput::UseAddress(arr_to_addr(arr) + AddressDiff(x as i32))
},
AbsoluteY => {
AddressingMode::AbsoluteY => {
// Use [u8, ..2] from instruction as address, add Y
// (Output: a 16-bit address)
UseAddress(arr_to_addr(arr) + AddressDiff(y as i32))
OpInput::UseAddress(arr_to_addr(arr) + AddressDiff(y as i32))
},
Indirect => {
AddressingMode::Indirect => {
// Use [u8, ..2] from instruction as an address. Interpret the
// two bytes starting at that address as an address.
// (Output: a 16-bit address)
let slice = memory.get_slice(arr_to_addr(arr), AddressDiff(2));
UseAddress(arr_to_addr(slice))
OpInput::UseAddress(arr_to_addr(slice))
},
IndexedIndirectX => {
AddressingMode::IndexedIndirectX => {
// Use [u8, ..1] from instruction
// Add to X register with 0-page wraparound, like ZeroPageX.
// This is where the absolute (16-bit) target address is stored.
@ -238,9 +238,9 @@ impl AddressingMode {
let start = arr[0] + x;
let slice = memory.get_slice(Address(start as u16),
AddressDiff(2));
UseAddress(arr_to_addr(slice))
OpInput::UseAddress(arr_to_addr(slice))
},
IndirectIndexedY => {
AddressingMode::IndirectIndexedY => {
// Use [u8, ..1] from instruction
// This is where the absolute (16-bit) target address is stored.
// Add Y register to this address to get the final address
@ -248,270 +248,270 @@ impl AddressingMode {
let start = arr[0];
let slice = memory.get_slice(Address(start as u16),
AddressDiff(2));
UseAddress(arr_to_addr(slice) + AddressDiff(y as i32))
OpInput::UseAddress(arr_to_addr(slice) + AddressDiff(y as i32))
},
}
}
}
pub type DecodedInstr = (Instruction, AMOut);
pub type DecodedInstr = (Instruction, OpInput);
pub static OPCODES: [Option<(Instruction, AddressingMode)>, ..256] = [
/*0x00*/ Some((BRK, Implied)),
/*0x01*/ Some((ORA, IndexedIndirectX)),
/*0x00*/ Some((Instruction::BRK, AddressingMode::Implied)),
/*0x01*/ Some((Instruction::ORA, AddressingMode::IndexedIndirectX)),
/*0x02*/ None,
/*0x03*/ None,
/*0x04*/ None,
/*0x05*/ Some((ORA, ZeroPage)),
/*0x06*/ Some((ASL, ZeroPage)),
/*0x05*/ Some((Instruction::ORA, AddressingMode::ZeroPage)),
/*0x06*/ Some((Instruction::ASL, AddressingMode::ZeroPage)),
/*0x07*/ None,
/*0x08*/ Some((PHP, Implied)),
/*0x09*/ Some((ORA, Immediate)),
/*0x0A*/ Some((ASL, Accumulator)),
/*0x08*/ Some((Instruction::PHP, AddressingMode::Implied)),
/*0x09*/ Some((Instruction::ORA, AddressingMode::Immediate)),
/*0x0A*/ Some((Instruction::ASL, AddressingMode::Accumulator)),
/*0x0B*/ None,
/*0x0C*/ None,
/*0x0D*/ Some((ORA, Absolute)),
/*0x0E*/ Some((ASL, Absolute)),
/*0x0D*/ Some((Instruction::ORA, AddressingMode::Absolute)),
/*0x0E*/ Some((Instruction::ASL, AddressingMode::Absolute)),
/*0x0F*/ None,
/*0x10*/ Some((BPL, Relative)),
/*0x11*/ Some((ORA, IndirectIndexedY)),
/*0x10*/ Some((Instruction::BPL, AddressingMode::Relative)),
/*0x11*/ Some((Instruction::ORA, AddressingMode::IndirectIndexedY)),
/*0x12*/ None,
/*0x13*/ None,
/*0x14*/ None,
/*0x15*/ Some((ORA, ZeroPageX)),
/*0x16*/ Some((ASL, ZeroPageX)),
/*0x15*/ Some((Instruction::ORA, AddressingMode::ZeroPageX)),
/*0x16*/ Some((Instruction::ASL, AddressingMode::ZeroPageX)),
/*0x17*/ None,
/*0x18*/ Some((CLC, Implied)),
/*0x19*/ Some((ORA, AbsoluteY)),
/*0x18*/ Some((Instruction::CLC, AddressingMode::Implied)),
/*0x19*/ Some((Instruction::ORA, AddressingMode::AbsoluteY)),
/*0x1A*/ None,
/*0x1B*/ None,
/*0x1C*/ None,
/*0x1D*/ Some((ORA, AbsoluteX)),
/*0x1E*/ Some((ASL, AbsoluteX)),
/*0x1D*/ Some((Instruction::ORA, AddressingMode::AbsoluteX)),
/*0x1E*/ Some((Instruction::ASL, AddressingMode::AbsoluteX)),
/*0x1F*/ None,
/*0x20*/ Some((JSR, Absolute)),
/*0x21*/ Some((AND, IndexedIndirectX)),
/*0x20*/ Some((Instruction::JSR, AddressingMode::Absolute)),
/*0x21*/ Some((Instruction::AND, AddressingMode::IndexedIndirectX)),
/*0x22*/ None,
/*0x23*/ None,
/*0x24*/ Some((BIT, ZeroPage)),
/*0x25*/ Some((AND, ZeroPage)),
/*0x26*/ Some((ROL, ZeroPage)),
/*0x24*/ Some((Instruction::BIT, AddressingMode::ZeroPage)),
/*0x25*/ Some((Instruction::AND, AddressingMode::ZeroPage)),
/*0x26*/ Some((Instruction::ROL, AddressingMode::ZeroPage)),
/*0x27*/ None,
/*0x28*/ Some((PLP, Implied)),
/*0x29*/ Some((AND, Immediate)),
/*0x2A*/ Some((ROL, Accumulator)),
/*0x28*/ Some((Instruction::PLP, AddressingMode::Implied)),
/*0x29*/ Some((Instruction::AND, AddressingMode::Immediate)),
/*0x2A*/ Some((Instruction::ROL, AddressingMode::Accumulator)),
/*0x2B*/ None,
/*0x2C*/ Some((BIT, Absolute)),
/*0x2D*/ Some((AND, Absolute)),
/*0x2E*/ Some((ROL, Absolute)),
/*0x2C*/ Some((Instruction::BIT, AddressingMode::Absolute)),
/*0x2D*/ Some((Instruction::AND, AddressingMode::Absolute)),
/*0x2E*/ Some((Instruction::ROL, AddressingMode::Absolute)),
/*0x2F*/ None,
/*0x30*/ Some((BMI, Relative)),
/*0x31*/ Some((AND, IndirectIndexedY)),
/*0x30*/ Some((Instruction::BMI, AddressingMode::Relative)),
/*0x31*/ Some((Instruction::AND, AddressingMode::IndirectIndexedY)),
/*0x32*/ None,
/*0x33*/ None,
/*0x34*/ None,
/*0x35*/ Some((AND, ZeroPageX)),
/*0x36*/ Some((ROL, ZeroPageX)),
/*0x35*/ Some((Instruction::AND, AddressingMode::ZeroPageX)),
/*0x36*/ Some((Instruction::ROL, AddressingMode::ZeroPageX)),
/*0x37*/ None,
/*0x38*/ Some((SEC, Implied)),
/*0x39*/ Some((AND, AbsoluteY)),
/*0x38*/ Some((Instruction::SEC, AddressingMode::Implied)),
/*0x39*/ Some((Instruction::AND, AddressingMode::AbsoluteY)),
/*0x3A*/ None,
/*0x3B*/ None,
/*0x3C*/ None,
/*0x3D*/ Some((AND, AbsoluteX)),
/*0x3E*/ Some((ROL, AbsoluteX)),
/*0x3D*/ Some((Instruction::AND, AddressingMode::AbsoluteX)),
/*0x3E*/ Some((Instruction::ROL, AddressingMode::AbsoluteX)),
/*0x3F*/ None,
/*0x40*/ Some((RTI, Implied)),
/*0x41*/ Some((EOR, IndexedIndirectX)),
/*0x40*/ Some((Instruction::RTI, AddressingMode::Implied)),
/*0x41*/ Some((Instruction::EOR, AddressingMode::IndexedIndirectX)),
/*0x42*/ None,
/*0x43*/ None,
/*0x44*/ None,
/*0x45*/ Some((EOR, ZeroPage)),
/*0x46*/ Some((LSR, ZeroPage)),
/*0x45*/ Some((Instruction::EOR, AddressingMode::ZeroPage)),
/*0x46*/ Some((Instruction::LSR, AddressingMode::ZeroPage)),
/*0x47*/ None,
/*0x48*/ Some((PHA, Implied)),
/*0x49*/ Some((EOR, Immediate)),
/*0x4A*/ Some((LSR, Accumulator)),
/*0x48*/ Some((Instruction::PHA, AddressingMode::Implied)),
/*0x49*/ Some((Instruction::EOR, AddressingMode::Immediate)),
/*0x4A*/ Some((Instruction::LSR, AddressingMode::Accumulator)),
/*0x4B*/ None,
/*0x4C*/ Some((JMP, Absolute)),
/*0x4D*/ Some((EOR, Absolute)),
/*0x4E*/ Some((LSR, Absolute)),
/*0x4C*/ Some((Instruction::JMP, AddressingMode::Absolute)),
/*0x4D*/ Some((Instruction::EOR, AddressingMode::Absolute)),
/*0x4E*/ Some((Instruction::LSR, AddressingMode::Absolute)),
/*0x4F*/ None,
/*0x50*/ Some((BVC, Relative)),
/*0x51*/ Some((EOR, IndirectIndexedY)),
/*0x50*/ Some((Instruction::BVC, AddressingMode::Relative)),
/*0x51*/ Some((Instruction::EOR, AddressingMode::IndirectIndexedY)),
/*0x52*/ None,
/*0x53*/ None,
/*0x54*/ None,
/*0x55*/ Some((EOR, ZeroPageX)),
/*0x56*/ Some((LSR, ZeroPageX)),
/*0x55*/ Some((Instruction::EOR, AddressingMode::ZeroPageX)),
/*0x56*/ Some((Instruction::LSR, AddressingMode::ZeroPageX)),
/*0x57*/ None,
/*0x58*/ None,
/*0x59*/ Some((EOR, AbsoluteY)),
/*0x59*/ Some((Instruction::EOR, AddressingMode::AbsoluteY)),
/*0x5A*/ None,
/*0x5B*/ None,
/*0x5C*/ None,
/*0x5D*/ Some((EOR, AbsoluteX)),
/*0x5E*/ Some((LSR, AbsoluteX)),
/*0x5D*/ Some((Instruction::EOR, AddressingMode::AbsoluteX)),
/*0x5E*/ Some((Instruction::LSR, AddressingMode::AbsoluteX)),
/*0x5F*/ None,
/*0x60*/ Some((RTS, Implied)),
/*0x61*/ Some((ADC, IndexedIndirectX)),
/*0x60*/ Some((Instruction::RTS, AddressingMode::Implied)),
/*0x61*/ Some((Instruction::ADC, AddressingMode::IndexedIndirectX)),
/*0x62*/ None,
/*0x63*/ None,
/*0x64*/ None,
/*0x65*/ Some((ADC, ZeroPage)),
/*0x66*/ Some((ROR, ZeroPage)),
/*0x65*/ Some((Instruction::ADC, AddressingMode::ZeroPage)),
/*0x66*/ Some((Instruction::ROR, AddressingMode::ZeroPage)),
/*0x67*/ None,
/*0x68*/ Some((PLA, Implied)),
/*0x69*/ Some((ADC, Immediate)),
/*0x6A*/ Some((ROR, Accumulator)),
/*0x68*/ Some((Instruction::PLA, AddressingMode::Implied)),
/*0x69*/ Some((Instruction::ADC, AddressingMode::Immediate)),
/*0x6A*/ Some((Instruction::ROR, AddressingMode::Accumulator)),
/*0x6B*/ None,
/*0x6C*/ Some((JMP, Indirect)),
/*0x6D*/ Some((ADC, Absolute)),
/*0x6E*/ Some((ROR, Absolute)),
/*0x6C*/ Some((Instruction::JMP, AddressingMode::Indirect)),
/*0x6D*/ Some((Instruction::ADC, AddressingMode::Absolute)),
/*0x6E*/ Some((Instruction::ROR, AddressingMode::Absolute)),
/*0x6F*/ None,
/*0x70*/ Some((BVS, Relative)),
/*0x71*/ Some((ADC, IndirectIndexedY)),
/*0x70*/ Some((Instruction::BVS, AddressingMode::Relative)),
/*0x71*/ Some((Instruction::ADC, AddressingMode::IndirectIndexedY)),
/*0x72*/ None,
/*0x73*/ None,
/*0x74*/ None,
/*0x75*/ Some((ADC, ZeroPageX)),
/*0x76*/ Some((ROR, ZeroPageX)),
/*0x75*/ Some((Instruction::ADC, AddressingMode::ZeroPageX)),
/*0x76*/ Some((Instruction::ROR, AddressingMode::ZeroPageX)),
/*0x77*/ None,
/*0x78*/ Some((SEI, Implied)),
/*0x79*/ Some((ADC, AbsoluteY)),
/*0x78*/ Some((Instruction::SEI, AddressingMode::Implied)),
/*0x79*/ Some((Instruction::ADC, AddressingMode::AbsoluteY)),
/*0x7A*/ None,
/*0x7B*/ None,
/*0x7C*/ None,
/*0x7D*/ Some((ADC, AbsoluteX)),
/*0x7E*/ Some((ROR, AbsoluteX)),
/*0x7D*/ Some((Instruction::ADC, AddressingMode::AbsoluteX)),
/*0x7E*/ Some((Instruction::ROR, AddressingMode::AbsoluteX)),
/*0x7F*/ None,
/*0x80*/ None,
/*0x81*/ Some((STA, IndexedIndirectX)),
/*0x81*/ Some((Instruction::STA, AddressingMode::IndexedIndirectX)),
/*0x82*/ None,
/*0x83*/ None,
/*0x84*/ Some((STY, ZeroPage)),
/*0x85*/ Some((STA, ZeroPage)),
/*0x86*/ Some((STX, ZeroPage)),
/*0x84*/ Some((Instruction::STY, AddressingMode::ZeroPage)),
/*0x85*/ Some((Instruction::STA, AddressingMode::ZeroPage)),
/*0x86*/ Some((Instruction::STX, AddressingMode::ZeroPage)),
/*0x87*/ None,
/*0x88*/ Some((DEY, Implied)),
/*0x88*/ Some((Instruction::DEY, AddressingMode::Implied)),
/*0x89*/ None,
/*0x8A*/ Some((TXA, Implied)),
/*0x8A*/ Some((Instruction::TXA, AddressingMode::Implied)),
/*0x8B*/ None,
/*0x8C*/ Some((STY, Absolute)),
/*0x8D*/ Some((STA, Absolute)),
/*0x8E*/ Some((STX, Absolute)),
/*0x8C*/ Some((Instruction::STY, AddressingMode::Absolute)),
/*0x8D*/ Some((Instruction::STA, AddressingMode::Absolute)),
/*0x8E*/ Some((Instruction::STX, AddressingMode::Absolute)),
/*0x8F*/ None,
/*0x90*/ Some((BCC, Relative)),
/*0x91*/ Some((STA, IndirectIndexedY)),
/*0x90*/ Some((Instruction::BCC, AddressingMode::Relative)),
/*0x91*/ Some((Instruction::STA, AddressingMode::IndirectIndexedY)),
/*0x92*/ None,
/*0x93*/ None,
/*0x94*/ Some((STY, ZeroPageX)),
/*0x95*/ Some((STA, ZeroPageX)),
/*0x96*/ Some((STX, ZeroPageY)),
/*0x94*/ Some((Instruction::STY, AddressingMode::ZeroPageX)),
/*0x95*/ Some((Instruction::STA, AddressingMode::ZeroPageX)),
/*0x96*/ Some((Instruction::STX, AddressingMode::ZeroPageY)),
/*0x97*/ None,
/*0x98*/ Some((TYA, Implied)),
/*0x99*/ Some((STA, AbsoluteY)),
/*0x9A*/ Some((TXS, Implied)),
/*0x98*/ Some((Instruction::TYA, AddressingMode::Implied)),
/*0x99*/ Some((Instruction::STA, AddressingMode::AbsoluteY)),
/*0x9A*/ Some((Instruction::TXS, AddressingMode::Implied)),
/*0x9B*/ None,
/*0x9C*/ None,
/*0x9D*/ Some((STA, AbsoluteX)),
/*0x9D*/ Some((Instruction::STA, AddressingMode::AbsoluteX)),
/*0x9E*/ None,
/*0x9F*/ None,
/*0xA0*/ Some((LDY, Immediate)),
/*0xA1*/ Some((LDA, IndexedIndirectX)),
/*0xA2*/ Some((LDX, Immediate)),
/*0xA0*/ Some((Instruction::LDY, AddressingMode::Immediate)),
/*0xA1*/ Some((Instruction::LDA, AddressingMode::IndexedIndirectX)),
/*0xA2*/ Some((Instruction::LDX, AddressingMode::Immediate)),
/*0xA3*/ None,
/*0xA4*/ Some((LDY, ZeroPage)),
/*0xA5*/ Some((LDA, ZeroPage)),
/*0xA6*/ Some((LDX, ZeroPage)),
/*0xA4*/ Some((Instruction::LDY, AddressingMode::ZeroPage)),
/*0xA5*/ Some((Instruction::LDA, AddressingMode::ZeroPage)),
/*0xA6*/ Some((Instruction::LDX, AddressingMode::ZeroPage)),
/*0xA7*/ None,
/*0xA8*/ Some((TAY, Implied)),
/*0xA9*/ Some((LDA, Immediate)),
/*0xAA*/ Some((TAX, Implied)),
/*0xA8*/ Some((Instruction::TAY, AddressingMode::Implied)),
/*0xA9*/ Some((Instruction::LDA, AddressingMode::Immediate)),
/*0xAA*/ Some((Instruction::TAX, AddressingMode::Implied)),
/*0xAB*/ None,
/*0xAC*/ Some((LDY, Absolute)),
/*0xAD*/ Some((LDA, Absolute)),
/*0xAE*/ Some((LDX, Absolute)),
/*0xAC*/ Some((Instruction::LDY, AddressingMode::Absolute)),
/*0xAD*/ Some((Instruction::LDA, AddressingMode::Absolute)),
/*0xAE*/ Some((Instruction::LDX, AddressingMode::Absolute)),
/*0xAF*/ None,
/*0xB0*/ Some((BCS, Relative)),
/*0xB1*/ Some((LDA, IndirectIndexedY)),
/*0xB0*/ Some((Instruction::BCS, AddressingMode::Relative)),
/*0xB1*/ Some((Instruction::LDA, AddressingMode::IndirectIndexedY)),
/*0xB2*/ None,
/*0xB3*/ None,
/*0xB4*/ Some((LDY, ZeroPageX)),
/*0xB5*/ Some((LDA, ZeroPageX)),
/*0xB6*/ Some((LDX, ZeroPageY)),
/*0xB4*/ Some((Instruction::LDY, AddressingMode::ZeroPageX)),
/*0xB5*/ Some((Instruction::LDA, AddressingMode::ZeroPageX)),
/*0xB6*/ Some((Instruction::LDX, AddressingMode::ZeroPageY)),
/*0xB7*/ None,
/*0xB8*/ Some((CLV, Implied)),
/*0xB9*/ Some((LDA, AbsoluteY)),
/*0xBA*/ Some((TSX, Implied)),
/*0xB8*/ Some((Instruction::CLV, AddressingMode::Implied)),
/*0xB9*/ Some((Instruction::LDA, AddressingMode::AbsoluteY)),
/*0xBA*/ Some((Instruction::TSX, AddressingMode::Implied)),
/*0xBB*/ None,
/*0xBC*/ Some((LDY, AbsoluteX)),
/*0xBD*/ Some((LDA, AbsoluteX)),
/*0xBE*/ Some((LDX, AbsoluteY)),
/*0xBC*/ Some((Instruction::LDY, AddressingMode::AbsoluteX)),
/*0xBD*/ Some((Instruction::LDA, AddressingMode::AbsoluteX)),
/*0xBE*/ Some((Instruction::LDX, AddressingMode::AbsoluteY)),
/*0xBF*/ None,
/*0xC0*/ Some((CPY, Immediate)),
/*0xC1*/ Some((CMP, IndexedIndirectX)),
/*0xC0*/ Some((Instruction::CPY, AddressingMode::Immediate)),
/*0xC1*/ Some((Instruction::CMP, AddressingMode::IndexedIndirectX)),
/*0xC2*/ None,
/*0xC3*/ None,
/*0xC4*/ Some((CPY, ZeroPage)),
/*0xC5*/ Some((CMP, ZeroPage)),
/*0xC6*/ Some((DEC, ZeroPage)),
/*0xC4*/ Some((Instruction::CPY, AddressingMode::ZeroPage)),
/*0xC5*/ Some((Instruction::CMP, AddressingMode::ZeroPage)),
/*0xC6*/ Some((Instruction::DEC, AddressingMode::ZeroPage)),
/*0xC7*/ None,
/*0xC8*/ Some((INY, Implied)),
/*0xC9*/ Some((CMP, Immediate)),
/*0xCA*/ Some((DEX, Implied)),
/*0xC8*/ Some((Instruction::INY, AddressingMode::Implied)),
/*0xC9*/ Some((Instruction::CMP, AddressingMode::Immediate)),
/*0xCA*/ Some((Instruction::DEX, AddressingMode::Implied)),
/*0xCB*/ None,
/*0xCC*/ Some((CPY, Absolute)),
/*0xCD*/ Some((CMP, Absolute)),
/*0xCE*/ Some((DEC, Absolute)),
/*0xCC*/ Some((Instruction::CPY, AddressingMode::Absolute)),
/*0xCD*/ Some((Instruction::CMP, AddressingMode::Absolute)),
/*0xCE*/ Some((Instruction::DEC, AddressingMode::Absolute)),
/*0xCF*/ None,
/*0xD0*/ Some((BNE, Relative)),
/*0xD1*/ Some((CMP, IndirectIndexedY)),
/*0xD0*/ Some((Instruction::BNE, AddressingMode::Relative)),
/*0xD1*/ Some((Instruction::CMP, AddressingMode::IndirectIndexedY)),
/*0xD2*/ None,
/*0xD3*/ None,
/*0xD4*/ None,
/*0xD5*/ Some((CMP, ZeroPageX)),
/*0xD6*/ Some((DEC, ZeroPageX)),
/*0xD5*/ Some((Instruction::CMP, AddressingMode::ZeroPageX)),
/*0xD6*/ Some((Instruction::DEC, AddressingMode::ZeroPageX)),
/*0xD7*/ None,
/*0xD8*/ Some((CLD, Implied)),
/*0xD9*/ Some((CMP, AbsoluteY)),
/*0xD8*/ Some((Instruction::CLD, AddressingMode::Implied)),
/*0xD9*/ Some((Instruction::CMP, AddressingMode::AbsoluteY)),
/*0xDA*/ None,
/*0xDB*/ None,
/*0xDC*/ None,
/*0xDD*/ Some((CMP, AbsoluteX)),
/*0xDE*/ Some((DEC, AbsoluteX)),
/*0xDD*/ Some((Instruction::CMP, AddressingMode::AbsoluteX)),
/*0xDE*/ Some((Instruction::DEC, AddressingMode::AbsoluteX)),
/*0xDF*/ None,
/*0xE0*/ Some((CPX, Immediate)),
/*0xE1*/ Some((SBC, IndexedIndirectX)),
/*0xE0*/ Some((Instruction::CPX, AddressingMode::Immediate)),
/*0xE1*/ Some((Instruction::SBC, AddressingMode::IndexedIndirectX)),
/*0xE2*/ None,
/*0xE3*/ None,
/*0xE4*/ Some((CPX, ZeroPage)),
/*0xE5*/ Some((SBC, ZeroPage)),
/*0xE6*/ Some((INC, ZeroPage)),
/*0xE4*/ Some((Instruction::CPX, AddressingMode::ZeroPage)),
/*0xE5*/ Some((Instruction::SBC, AddressingMode::ZeroPage)),
/*0xE6*/ Some((Instruction::INC, AddressingMode::ZeroPage)),
/*0xE7*/ None,
/*0xE8*/ Some((INX, Implied)),
/*0xE9*/ Some((SBC, Immediate)),
/*0xEA*/ Some((NOP, Implied)),
/*0xE8*/ Some((Instruction::INX, AddressingMode::Implied)),
/*0xE9*/ Some((Instruction::SBC, AddressingMode::Immediate)),
/*0xEA*/ Some((Instruction::NOP, AddressingMode::Implied)),
/*0xEB*/ None,
/*0xEC*/ Some((CPX, Absolute)),
/*0xED*/ Some((SBC, Absolute)),
/*0xEE*/ Some((INC, Absolute)),
/*0xEC*/ Some((Instruction::CPX, AddressingMode::Absolute)),
/*0xED*/ Some((Instruction::SBC, AddressingMode::Absolute)),
/*0xEE*/ Some((Instruction::INC, AddressingMode::Absolute)),
/*0xEF*/ None,
/*0xF0*/ Some((BEQ, Relative)),
/*0xF1*/ Some((SBC, IndirectIndexedY)),
/*0xF0*/ Some((Instruction::BEQ, AddressingMode::Relative)),
/*0xF1*/ Some((Instruction::SBC, AddressingMode::IndirectIndexedY)),
/*0xF2*/ None,
/*0xF3*/ None,
/*0xF4*/ None,
/*0xF5*/ Some((SBC, ZeroPageX)),
/*0xF6*/ Some((INC, ZeroPageX)),
/*0xF5*/ Some((Instruction::SBC, AddressingMode::ZeroPageX)),
/*0xF6*/ Some((Instruction::INC, AddressingMode::ZeroPageX)),
/*0xF7*/ None,
/*0xF8*/ Some((SED, Implied)),
/*0xF9*/ Some((SBC, AbsoluteY)),
/*0xF8*/ Some((Instruction::SED, AddressingMode::Implied)),
/*0xF9*/ Some((Instruction::SBC, AddressingMode::AbsoluteY)),
/*0xFA*/ None,
/*0xFB*/ None,
/*0xFC*/ None,
/*0xFD*/ Some((SBC, AbsoluteX)),
/*0xFE*/ Some((INC, AbsoluteX)),
/*0xFD*/ Some((Instruction::SBC, AddressingMode::AbsoluteX)),
/*0xFE*/ Some((Instruction::INC, AddressingMode::AbsoluteX)),
/*0xFF*/ None,
];

View File

@ -29,7 +29,7 @@ use std;
use address::{Address, AddressDiff};
use instruction;
use instruction::{DecodedInstr};
use instruction::{DecodedInstr, Instruction, OpInput};
use memory::Memory;
use registers::{ Registers, StackPointer, Status, StatusArgs };
use registers::{ PS_NEGATIVE, PS_DECIMAL_MODE, PS_OVERFLOW, PS_ZERO, PS_CARRY,
@ -78,25 +78,25 @@ impl Machine {
pub fn execute_instruction(&mut self, decoded_instr: DecodedInstr) {
match decoded_instr {
(instruction::ADC, instruction::UseImmediate(val)) => {
(Instruction::ADC, OpInput::UseImmediate(val)) => {
debug!("add with carry immediate: {}", val);
self.add_with_carry(val as i8);
}
(instruction::ADC, instruction::UseAddress(addr)) => {
(Instruction::ADC, OpInput::UseAddress(addr)) => {
let val = self.memory.get_byte(addr) as i8;
debug!("add with carry. address: {}. value: {}", addr, val);
self.add_with_carry(val);
}
(instruction::AND, instruction::UseImmediate(val)) => {
(Instruction::AND, OpInput::UseImmediate(val)) => {
self.and(val as i8);
}
(instruction::AND, instruction::UseAddress(addr)) => {
(Instruction::AND, OpInput::UseAddress(addr)) => {
let val = self.memory.get_byte(addr) as i8;
self.and(val as i8);
}
(instruction::ASL, instruction::UseImplied) => {
(Instruction::ASL, OpInput::UseImplied) => {
// Accumulator mode
let mut val = self.registers.accumulator as u8;
Machine::shift_left_with_flags(&mut val,
@ -104,31 +104,31 @@ impl Machine {
self.registers.accumulator = val as i8;
}
(instruction::ASL, instruction::UseAddress(addr)) => {
(Instruction::ASL, OpInput::UseAddress(addr)) => {
Machine::shift_left_with_flags(
self.memory.get_byte_mut_ref(addr),
&mut self.registers.status);
}
(instruction::BCC, instruction::UseRelative(rel)) => {
(Instruction::BCC, OpInput::UseRelative(rel)) => {
let addr = self.registers.program_counter
+ AddressDiff(rel as i32);
self.branch_if_carry_clear(addr);
}
(instruction::BCS, instruction::UseRelative(rel)) => {
(Instruction::BCS, OpInput::UseRelative(rel)) => {
let addr = self.registers.program_counter
+ AddressDiff(rel as i32);
self.branch_if_carry_set(addr);
}
(instruction::BEQ, instruction::UseRelative(rel)) => {
(Instruction::BEQ, OpInput::UseRelative(rel)) => {
let addr = self.registers.program_counter
+ AddressDiff(rel as i32);
self.branch_if_equal(addr);
}
(instruction::BIT, instruction::UseAddress(addr)) => {
(Instruction::BIT, OpInput::UseAddress(addr)) => {
let a: u8 = self.registers.accumulator as u8;
let m: u8 = self.memory.get_byte(addr);
let res = a & m;
@ -150,163 +150,163 @@ impl Machine {
..StatusArgs::none() } ));
}
(instruction::BMI, instruction::UseRelative(rel)) => {
(Instruction::BMI, OpInput::UseRelative(rel)) => {
let addr = self.registers.program_counter
+ AddressDiff(rel as i32);
debug!("branch if minus relative. address: {}", addr);
self.branch_if_minus(addr);
}
(instruction::BPL, instruction::UseRelative(rel)) => {
(Instruction::BPL, OpInput::UseRelative(rel)) => {
let addr = self.registers.program_counter
+ AddressDiff(rel as i32);
self.branch_if_positive(addr);
}
(instruction::BVC, instruction::UseRelative(rel)) => {
(Instruction::BVC, OpInput::UseRelative(rel)) => {
let addr = self.registers.program_counter
+ AddressDiff(rel as i32);
self.branch_if_overflow_clear(addr);
}
(instruction::BVS, instruction::UseRelative(rel)) => {
(Instruction::BVS, OpInput::UseRelative(rel)) => {
let addr = self.registers.program_counter
+ AddressDiff(rel as i32);
self.branch_if_overflow_set(addr);
}
(instruction::CLC, instruction::UseImplied) => {
(Instruction::CLC, OpInput::UseImplied) => {
self.registers.status.and(!PS_CARRY);
}
(instruction::CLD, instruction::UseImplied) => {
(Instruction::CLD, OpInput::UseImplied) => {
self.registers.status.and(!PS_DECIMAL_MODE);
}
(instruction::CLI, instruction::UseImplied) => {
(Instruction::CLI, OpInput::UseImplied) => {
self.registers.status.and(!PS_DISABLE_INTERRUPTS);
}
(instruction::CLV, instruction::UseImplied) => {
(Instruction::CLV, OpInput::UseImplied) => {
self.registers.status.and(!PS_OVERFLOW);
}
(instruction::CMP, instruction::UseImmediate(val)) => {
(Instruction::CMP, OpInput::UseImmediate(val)) => {
self.compare_with_a_register(val);
}
(instruction::CMP, instruction::UseAddress(addr)) => {
(Instruction::CMP, OpInput::UseAddress(addr)) => {
let val = self.memory.get_byte(addr);
self.compare_with_a_register(val);
}
(instruction::CPX, instruction::UseImmediate(val)) => {
(Instruction::CPX, OpInput::UseImmediate(val)) => {
self.compare_with_x_register(val);
}
(instruction::CPX, instruction::UseAddress(addr)) => {
(Instruction::CPX, OpInput::UseAddress(addr)) => {
let val = self.memory.get_byte(addr);
self.compare_with_x_register(val);
}
(instruction::CPY, instruction::UseImmediate(val)) => {
(Instruction::CPY, OpInput::UseImmediate(val)) => {
self.compare_with_y_register(val);
}
(instruction::CPY, instruction::UseAddress(addr)) => {
(Instruction::CPY, OpInput::UseAddress(addr)) => {
let val = self.memory.get_byte(addr);
self.compare_with_y_register(val);
}
(instruction::DEC, instruction::UseAddress(addr)) => {
(Instruction::DEC, OpInput::UseAddress(addr)) => {
self.decrement_memory(addr)
}
(instruction::DEX, instruction::UseImplied) => {
(Instruction::DEX, OpInput::UseImplied) => {
self.dec_x();
}
(instruction::EOR, instruction::UseImmediate(val)) => {
(Instruction::EOR, OpInput::UseImmediate(val)) => {
self.exclusive_or(val);
}
(instruction::EOR, instruction::UseAddress(addr)) => {
(Instruction::EOR, OpInput::UseAddress(addr)) => {
let val = self.memory.get_byte(addr);
self.exclusive_or(val);
}
(instruction::INC, instruction::UseAddress(addr)) => {
(Instruction::INC, OpInput::UseAddress(addr)) => {
let m = self.memory.get_byte(addr);
let m = m + 1;
self.memory.set_byte(addr, m);
let i = m as i8;
Machine::set_flags_from_i8(&mut self.registers.status, i);
}
(instruction::INX, instruction::UseImplied) => {
(Instruction::INX, OpInput::UseImplied) => {
let x = self.registers.index_x + 1;
self.load_x_register(x);
}
(instruction::INY, instruction::UseImplied) => {
(Instruction::INY, OpInput::UseImplied) => {
let y = self.registers.index_y + 1;
self.load_y_register(y);
}
(instruction::JMP, instruction::UseAddress(addr)) => {
(Instruction::JMP, OpInput::UseAddress(addr)) => {
self.jump(addr)
}
(instruction::LDA, instruction::UseImmediate(val)) => {
(Instruction::LDA, OpInput::UseImmediate(val)) => {
debug!("load A immediate: {}", val);
self.load_accumulator(val as i8);
}
(instruction::LDA, instruction::UseAddress(addr)) => {
(Instruction::LDA, OpInput::UseAddress(addr)) => {
let val = self.memory.get_byte(addr);
debug!("load A. address: {}. value: {}", addr, val);
self.load_accumulator(val as i8);
}
(instruction::LDX, instruction::UseImmediate(val)) => {
(Instruction::LDX, OpInput::UseImmediate(val)) => {
debug!("load X immediate: {}", val);
self.load_x_register(val as i8);
}
(instruction::LDX, instruction::UseAddress(addr)) => {
(Instruction::LDX, OpInput::UseAddress(addr)) => {
let val = self.memory.get_byte(addr);
debug!("load X. address: {}. value: {}", addr, val);
self.load_x_register(val as i8);
}
(instruction::LDY, instruction::UseImmediate(val)) => {
(Instruction::LDY, OpInput::UseImmediate(val)) => {
debug!("load Y immediate: {}", val);
self.load_y_register(val as i8);
}
(instruction::LDY, instruction::UseAddress(addr)) => {
(Instruction::LDY, OpInput::UseAddress(addr)) => {
let val = self.memory.get_byte(addr);
debug!("load Y. address: {}. value: {}", addr, val);
self.load_y_register(val as i8);
}
(instruction::LSR, instruction::UseImplied) => {
(Instruction::LSR, OpInput::UseImplied) => {
// Accumulator mode
let mut val = self.registers.accumulator as u8;
Machine::shift_right_with_flags(&mut val,
&mut self.registers.status);
self.registers.accumulator = val as i8;
}
(instruction::LSR, instruction::UseAddress(addr)) => {
(Instruction::LSR, OpInput::UseAddress(addr)) => {
Machine::shift_right_with_flags(
self.memory.get_byte_mut_ref(addr),
&mut self.registers.status);
}
(instruction::PHA, instruction::UseImplied) => {
(Instruction::PHA, OpInput::UseImplied) => {
// Push accumulator
let val = self.registers.accumulator as u8;
self.push_on_stack(val);
}
(instruction::PHP, instruction::UseImplied) => {
(Instruction::PHP, OpInput::UseImplied) => {
// Push status
let val = self.registers.status.bits();
self.push_on_stack(val);
}
(instruction::PLA, instruction::UseImplied) => {
(Instruction::PLA, OpInput::UseImplied) => {
// Pull accumulator
let val: u8 = self.pull_from_stack();
self.registers.accumulator = val as i8;
}
(instruction::PLP, instruction::UseImplied) => {
(Instruction::PLP, OpInput::UseImplied) => {
// Pull status
let val: u8 = self.pull_from_stack();
// The `truncate` here won't do anything because we have a
@ -315,92 +315,92 @@ impl Machine {
self.registers.status = Status::from_bits_truncate(val);
}
(instruction::ROL, instruction::UseImplied) => {
(Instruction::ROL, OpInput::UseImplied) => {
// Accumulator mode
let mut val = self.registers.accumulator as u8;
Machine::rotate_left_with_flags(&mut val,
&mut self.registers.status);
self.registers.accumulator = val as i8;
}
(instruction::ROL, instruction::UseAddress(addr)) => {
(Instruction::ROL, OpInput::UseAddress(addr)) => {
Machine::rotate_left_with_flags(
self.memory.get_byte_mut_ref(addr),
&mut self.registers.status);
}
(instruction::ROR, instruction::UseImplied) => {
(Instruction::ROR, OpInput::UseImplied) => {
// Accumulator mode
let mut val = self.registers.accumulator as u8;
Machine::rotate_right_with_flags(&mut val,
&mut self.registers.status);
self.registers.accumulator = val as i8;
}
(instruction::ROR, instruction::UseAddress(addr)) => {
(Instruction::ROR, OpInput::UseAddress(addr)) => {
Machine::rotate_right_with_flags(
self.memory.get_byte_mut_ref(addr),
&mut self.registers.status);
}
(instruction::SBC, instruction::UseImmediate(val)) => {
(Instruction::SBC, OpInput::UseImmediate(val)) => {
debug!("subtract with carry immediate: {}", val);
self.subtract_with_carry(val as i8);
}
(instruction::SBC, instruction::UseAddress(addr)) => {
(Instruction::SBC, OpInput::UseAddress(addr)) => {
let val = self.memory.get_byte(addr) as i8;
debug!("subtract with carry. address: {}. value: {}",
addr, val);
self.subtract_with_carry(val);
}
(instruction::SEC, instruction::UseImplied) => {
(Instruction::SEC, OpInput::UseImplied) => {
self.registers.status.or(PS_CARRY);
}
(instruction::SED, instruction::UseImplied) => {
(Instruction::SED, OpInput::UseImplied) => {
self.registers.status.or(PS_DECIMAL_MODE);
}
(instruction::SEI, instruction::UseImplied) => {
(Instruction::SEI, OpInput::UseImplied) => {
self.registers.status.or(PS_DISABLE_INTERRUPTS);
}
(instruction::STA, instruction::UseAddress(addr)) => {
(Instruction::STA, OpInput::UseAddress(addr)) => {
self.memory.set_byte(addr, self.registers.accumulator as u8);
}
(instruction::STX, instruction::UseAddress(addr)) => {
(Instruction::STX, OpInput::UseAddress(addr)) => {
self.memory.set_byte(addr, self.registers.index_x as u8);
}
(instruction::STY, instruction::UseAddress(addr)) => {
(Instruction::STY, OpInput::UseAddress(addr)) => {
self.memory.set_byte(addr, self.registers.index_y as u8);
}
(instruction::TAX, instruction::UseImplied) => {
(Instruction::TAX, OpInput::UseImplied) => {
let val = self.registers.accumulator;
self.load_x_register(val);
}
(instruction::TAY, instruction::UseImplied) => {
(Instruction::TAY, OpInput::UseImplied) => {
let val = self.registers.accumulator;
self.load_y_register(val);
}
(instruction::TSX, instruction::UseImplied) => {
(Instruction::TSX, OpInput::UseImplied) => {
let StackPointer(val) = self.registers.stack_pointer;
let val = val as i8;
self.load_x_register(val);
}
(instruction::TXA, instruction::UseImplied) => {
(Instruction::TXA, OpInput::UseImplied) => {
let val = self.registers.index_x;
self.load_accumulator(val);
}
(instruction::TXS, instruction::UseImplied) => {
(Instruction::TXS, OpInput::UseImplied) => {
// Note that this is the only 'transfer' instruction that does
// NOT set the zero and negative flags. (Because the target
// is the stack pointer)
let val = self.registers.index_x;
self.registers.stack_pointer = StackPointer(val as u8);
}
(instruction::TYA, instruction::UseImplied) => {
(Instruction::TYA, OpInput::UseImplied) => {
let val = self.registers.index_y;
self.load_accumulator(val);
}
(instruction::NOP, instruction::UseImplied) => {
(Instruction::NOP, OpInput::UseImplied) => {
debug!("NOP instruction");
}
(_, _) => {
@ -828,7 +828,7 @@ fn and_test() {
fn subtract_with_carry_test() {
let mut machine = Machine::new();
machine.execute_instruction((instruction::SEC, instruction::UseImplied));
machine.execute_instruction((Instruction::SEC, OpInput::UseImplied));
machine.registers.accumulator = 0;
machine.subtract_with_carry(1);
@ -838,7 +838,7 @@ fn subtract_with_carry_test() {
assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true);
assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);
machine.execute_instruction((instruction::SEC, instruction::UseImplied));
machine.execute_instruction((Instruction::SEC, OpInput::UseImplied));
machine.registers.accumulator = -128;
machine.subtract_with_carry(1);
assert_eq!(machine.registers.accumulator, 127);
@ -847,7 +847,7 @@ fn subtract_with_carry_test() {
assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
assert_eq!(machine.registers.status.contains(PS_OVERFLOW), true);
machine.execute_instruction((instruction::SEC, instruction::UseImplied));
machine.execute_instruction((Instruction::SEC, OpInput::UseImplied));
machine.registers.accumulator = 127;
machine.subtract_with_carry(-1);
assert_eq!(machine.registers.accumulator, -128);
@ -856,7 +856,7 @@ fn subtract_with_carry_test() {
assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true);
assert_eq!(machine.registers.status.contains(PS_OVERFLOW), true);
machine.execute_instruction((instruction::CLC, instruction::UseImplied));
machine.execute_instruction((Instruction::CLC, OpInput::UseImplied));
machine.registers.accumulator = -64;
machine.subtract_with_carry(64);
assert_eq!(machine.registers.accumulator, 127);
@ -865,7 +865,7 @@ fn subtract_with_carry_test() {
assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
assert_eq!(machine.registers.status.contains(PS_OVERFLOW), true);
machine.execute_instruction((instruction::SEC, instruction::UseImplied));
machine.execute_instruction((Instruction::SEC, OpInput::UseImplied));
machine.registers.accumulator = 0;
machine.subtract_with_carry(-128);
assert_eq!(machine.registers.accumulator, -128);
@ -874,7 +874,7 @@ fn subtract_with_carry_test() {
assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true);
assert_eq!(machine.registers.status.contains(PS_OVERFLOW), true);
machine.execute_instruction((instruction::CLC, instruction::UseImplied));
machine.execute_instruction((Instruction::CLC, OpInput::UseImplied));
machine.registers.accumulator = 0;
machine.subtract_with_carry(127);
assert_eq!(machine.registers.accumulator, -128);
@ -919,40 +919,40 @@ fn logical_shift_right_test() {
// Testing UseImplied version (which targets the accumulator) only, for now
let mut machine = Machine::new();
machine.execute_instruction((instruction::LDA,
instruction::UseImmediate(0)));
machine.execute_instruction((instruction::LSR,
instruction::UseImplied));
machine.execute_instruction((Instruction::LDA,
OpInput::UseImmediate(0)));
machine.execute_instruction((Instruction::LSR,
OpInput::UseImplied));
assert_eq!(machine.registers.accumulator, 0);
assert_eq!(machine.registers.status.contains(PS_CARRY), false);
assert_eq!(machine.registers.status.contains(PS_ZERO), true);
assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);
machine.execute_instruction((instruction::LDA,
instruction::UseImmediate(1)));
machine.execute_instruction((instruction::LSR,
instruction::UseImplied));
machine.execute_instruction((Instruction::LDA,
OpInput::UseImmediate(1)));
machine.execute_instruction((Instruction::LSR,
OpInput::UseImplied));
assert_eq!(machine.registers.accumulator, 0);
assert_eq!(machine.registers.status.contains(PS_CARRY), true);
assert_eq!(machine.registers.status.contains(PS_ZERO), true);
assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);
machine.execute_instruction((instruction::LDA,
instruction::UseImmediate(255)));
machine.execute_instruction((instruction::LSR,
instruction::UseImplied));
machine.execute_instruction((Instruction::LDA,
OpInput::UseImmediate(255)));
machine.execute_instruction((Instruction::LSR,
OpInput::UseImplied));
assert_eq!(machine.registers.accumulator, 0x7F);
assert_eq!(machine.registers.status.contains(PS_CARRY), true);
assert_eq!(machine.registers.status.contains(PS_ZERO), false);
assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);
machine.execute_instruction((instruction::LDA,
instruction::UseImmediate(254)));
machine.execute_instruction((instruction::LSR,
instruction::UseImplied));
machine.execute_instruction((Instruction::LDA,
OpInput::UseImmediate(254)));
machine.execute_instruction((Instruction::LSR,
OpInput::UseImplied));
assert_eq!(machine.registers.accumulator, 0x7F);
assert_eq!(machine.registers.status.contains(PS_CARRY), false);
assert_eq!(machine.registers.status.contains(PS_ZERO), false);
@ -1018,11 +1018,11 @@ fn jump_test() {
fn branch_if_carry_clear_test() {
let mut machine = Machine::new();
machine.execute_instruction((instruction::SEC, instruction::UseImplied));
machine.execute_instruction((Instruction::SEC, OpInput::UseImplied));
machine.branch_if_carry_clear(Address(0xABCD));
assert_eq!(machine.registers.program_counter, Address(0));
machine.execute_instruction((instruction::CLC, instruction::UseImplied));
machine.execute_instruction((Instruction::CLC, OpInput::UseImplied));
machine.branch_if_carry_clear(Address(0xABCD));
assert_eq!(machine.registers.program_counter, Address(0xABCD));
}
@ -1031,11 +1031,11 @@ fn branch_if_carry_clear_test() {
fn branch_if_carry_set_test() {
let mut machine = Machine::new();
machine.execute_instruction((instruction::CLC, instruction::UseImplied));
machine.execute_instruction((Instruction::CLC, OpInput::UseImplied));
machine.branch_if_carry_set(Address(0xABCD));
assert_eq!(machine.registers.program_counter, Address(0));
machine.execute_instruction((instruction::SEC, instruction::UseImplied));
machine.execute_instruction((Instruction::SEC, OpInput::UseImplied));
machine.branch_if_carry_set(Address(0xABCD));
assert_eq!(machine.registers.program_counter, Address(0xABCD));
}
@ -1113,14 +1113,15 @@ fn branch_if_overflow_set_test() {
assert_eq!(machine.registers.program_counter, Address(0xABCD));
}
#[cfg(test)]
fn compare_test_helper(
compare: |&mut Machine, u8|,
load_instruction: instruction::Instruction
load_instruction: Instruction
) {
let mut machine = Machine::new();
machine.execute_instruction(
(load_instruction, instruction::UseImmediate(127))
(load_instruction, OpInput::UseImmediate(127))
);
compare(&mut machine, 127);
@ -1130,7 +1131,7 @@ fn compare_test_helper(
machine.execute_instruction(
(load_instruction, instruction::UseImmediate(127))
(load_instruction, OpInput::UseImmediate(127))
);
compare(&mut machine, 1);
@ -1140,7 +1141,7 @@ fn compare_test_helper(
machine.execute_instruction(
(load_instruction, instruction::UseImmediate(1))
(load_instruction, OpInput::UseImmediate(1))
);
compare(&mut machine, 2);
@ -1150,7 +1151,7 @@ fn compare_test_helper(
machine.execute_instruction(
(load_instruction, instruction::UseImmediate(20))
(load_instruction, OpInput::UseImmediate(20))
);
compare(&mut machine, -50);
@ -1160,7 +1161,7 @@ fn compare_test_helper(
machine.execute_instruction(
(load_instruction, instruction::UseImmediate(1))
(load_instruction, OpInput::UseImmediate(1))
);
compare(&mut machine, -1);
@ -1170,7 +1171,7 @@ fn compare_test_helper(
machine.execute_instruction(
(load_instruction, instruction::UseImmediate(127))
(load_instruction, OpInput::UseImmediate(127))
);
compare(&mut machine, -128);
@ -1185,7 +1186,7 @@ fn compare_with_a_register_test() {
|machine: &mut Machine, val: u8| {
machine.compare_with_a_register(val);
},
instruction::LDA
Instruction::LDA
);
}
@ -1195,7 +1196,7 @@ fn compare_with_x_register_test() {
|machine: &mut Machine, val: u8| {
machine.compare_with_x_register(val);
},
instruction::LDX
Instruction::LDX
);
}
@ -1205,7 +1206,7 @@ fn compare_with_y_register_test() {
|machine: &mut Machine, val: u8| {
machine.compare_with_y_register(val);
},
instruction::LDY
Instruction::LDY
);
}
@ -1216,7 +1217,7 @@ fn exclusive_or_test() {
for a_before in range(0u8, 255u8) {
for val in range(0u8, 255u8) {
machine.execute_instruction(
(instruction::LDA, instruction::UseImmediate(a_before))
(Instruction::LDA, OpInput::UseImmediate(a_before))
);
machine.exclusive_or(val);