should be all legal opcodes

This commit is contained in:
Lauchmelder 2022-08-29 22:59:45 +02:00
parent 57a6168646
commit bc16c64e48
3 changed files with 106 additions and 77 deletions

View file

@ -33,6 +33,7 @@ macro_rules! abs_indexed_addr
let fetched_addr = (hi << 8) | lo; let fetched_addr = (hi << 8) | lo;
self.absolute_addr = fetched_addr.wrapping_add(self.$register as u16); self.absolute_addr = fetched_addr.wrapping_add(self.$register as u16);
self.additional_cycles = ((fetched_addr & 0xFF00) != (self.absolute_addr & 0xFF00)) as u8;
self.fetch_type = FetchType::Mem; self.fetch_type = FetchType::Mem;
@ -41,6 +42,25 @@ macro_rules! abs_indexed_addr
} }
} }
macro_rules! zpg_indexed_addr
{
($name: ident, $register: ident) =>
{
pub fn $name(&mut self)
{
let bus = self.bus.upgrade().unwrap();
let fetched_addr = bus.borrow().read_cpu(self.pc);
self.absolute_addr = fetched_addr.wrapping_add(self.$register) as u16;
self.pc += instr_size!($name) - 1;
self.fetch_type = FetchType::Mem;
print!("{: <40}", format!("${:02X},{} @ ${:04X}", fetched_addr, stringify!($register).to_uppercase(), self.absolute_addr));
}
}
}
pub type AddrFn = fn(&mut CPU); pub type AddrFn = fn(&mut CPU);
impl CPU impl CPU
@ -100,9 +120,7 @@ impl CPU
let target_addr = (hi << 8) | lo; let target_addr = (hi << 8) | lo;
self.absolute_addr = target_addr.wrapping_add(self.y as u16); self.absolute_addr = target_addr.wrapping_add(self.y as u16);
if (target_addr & 0xFF00) != (self.absolute_addr & 0xFF00) { self.additional_cycles = ((target_addr & 0xFF00) != (self.absolute_addr & 0xFF00)) as u8;
self.cycle += 1;
}
self.fetch_type = FetchType::Mem; self.fetch_type = FetchType::Mem;
@ -168,4 +186,8 @@ impl CPU
print!("{: <40}", format!("${:02X} = {:02X}", self.absolute_addr, bus.borrow().read_cpu(self.absolute_addr))) print!("{: <40}", format!("${:02X} = {:02X}", self.absolute_addr, bus.borrow().read_cpu(self.absolute_addr)))
} }
zpg_indexed_addr!(zpx, x);
zpg_indexed_addr!(zpy, y);
} }

View file

@ -12,7 +12,8 @@ pub enum FetchType
pub struct CPU pub struct CPU
{ {
pub cycle: u8, cycle: u8,
pub additional_cycles: u8,
total_cycles: u64, total_cycles: u64,
pub absolute_addr: u16, pub absolute_addr: u16,
@ -35,6 +36,7 @@ impl CPU
{ {
CPU { CPU {
cycle: 0, cycle: 0,
additional_cycles: 0,
total_cycles: 0, total_cycles: 0,
absolute_addr: 0, absolute_addr: 0,
@ -110,7 +112,8 @@ impl CPU
(instr.addressing)(self); (instr.addressing)(self);
(instr.action)(self); (instr.action)(self);
self.cycle += instr.cycles; self.cycle += instr.cycles + self.additional_cycles;
self.additional_cycles = 0;
println!("A:{:02X} X:{:02X} Y:{:02X} P:{:02X} SP:{:02X} CYC:{}", self.acc, self.x, self.y, self.p, self.sp, self.total_cycles); println!("A:{:02X} X:{:02X} Y:{:02X} P:{:02X} SP:{:02X} CYC:{}", self.acc, self.x, self.y, self.p, self.sp, self.total_cycles);
} }

View file

@ -20,7 +20,7 @@ pub struct Instruction
macro_rules! instr macro_rules! instr
{ {
($instr: ident, $addr: ident, $cyc: literal) => ($instr: ident, $addr: ident, $cyc: literal, $illegal: literal) =>
{ {
Option::Some(Instruction Option::Some(Instruction
{ {
@ -29,9 +29,11 @@ macro_rules! instr
cycles: $cyc, cycles: $cyc,
length: instr_size!($addr), length: instr_size!($addr),
name: Mnemonic::new(stringify!($instr), false) name: Mnemonic::new(stringify!($instr), $illegal)
}) })
} };
($instr: ident, $addr: ident, $cyc: literal) => { instr!($instr, $addr, $cyc, false) };
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -99,10 +101,10 @@ macro_rules! branch
{ {
let branch_target = $self.pc.wrapping_add($self.relative_addr as u16); let branch_target = $self.pc.wrapping_add($self.relative_addr as u16);
$self.cycle += 1; $self.additional_cycles += 1;
if (branch_target & 0xFF00) != ($self.pc & 0xFF00) // Branched to different page if (branch_target & 0xFF00) != ($self.pc & 0xFF00) // Branched to different page
{ {
$self.cycle += 1; $self.additional_cycles += 1;
} }
$self.pc = branch_target; $self.pc = branch_target;
@ -160,6 +162,8 @@ macro_rules! store_fn
{ {
let bus = self.bus.upgrade().unwrap(); let bus = self.bus.upgrade().unwrap();
bus.borrow_mut().write_cpu(self.absolute_addr, self.$register); bus.borrow_mut().write_cpu(self.absolute_addr, self.$register);
self.additional_cycles = 0;
} }
}; };
} }
@ -519,7 +523,7 @@ pub static INSTRUCTION_SET: [Option<Instruction>; 256] = [
/* 01 */ instr!(ora, idx, 6), /* 01 */ instr!(ora, idx, 6),
/* 02 */ Option::None, /* 02 */ Option::None,
/* 03 */ Option::None, /* 03 */ Option::None,
/* 04 */ Option::None, /* 04 */ instr!(nop, zpg, 3, true),
/* 05 */ instr!(ora, zpg, 3), /* 05 */ instr!(ora, zpg, 3),
/* 06 */ instr!(asl, zpg, 5), /* 06 */ instr!(asl, zpg, 5),
/* 07 */ Option::None, /* 07 */ Option::None,
@ -527,7 +531,7 @@ pub static INSTRUCTION_SET: [Option<Instruction>; 256] = [
/* 09 */ instr!(ora, imm, 2), /* 09 */ instr!(ora, imm, 2),
/* 0A */ instr!(asl, acc, 2), /* 0A */ instr!(asl, acc, 2),
/* 0B */ Option::None, /* 0B */ Option::None,
/* 0C */ Option::None, /* 0C */ instr!(nop, abs, 4, true),
/* 0D */ instr!(ora, abs, 4), /* 0D */ instr!(ora, abs, 4),
/* 0E */ instr!(asl, abs, 6), /* 0E */ instr!(asl, abs, 6),
/* 0F */ Option::None, /* 0F */ Option::None,
@ -536,17 +540,17 @@ pub static INSTRUCTION_SET: [Option<Instruction>; 256] = [
/* 11 */ instr!(ora, idy, 5), /* 11 */ instr!(ora, idy, 5),
/* 12 */ Option::None, /* 12 */ Option::None,
/* 13 */ Option::None, /* 13 */ Option::None,
/* 14 */ Option::None, /* 14 */ instr!(nop, zpx, 4, true),
/* 15 */ Option::None, /* 15 */ instr!(ora, zpx, 4),
/* 16 */ Option::None, /* 16 */ instr!(asl, zpx, 6),
/* 17 */ Option::None, /* 17 */ Option::None,
/* 18 */ instr!(clc, imp, 2), /* 18 */ instr!(clc, imp, 2),
/* 19 */ instr!(ora, aby, 4), /* 19 */ instr!(ora, aby, 4),
/* 1A */ Option::None, /* 1A */ instr!(nop, imp, 2, true),
/* 1B */ Option::None, /* 1B */ Option::None,
/* 1C */ Option::None, /* 1C */ instr!(nop, abx, 4, true),
/* 1D */ Option::None, /* 1D */ instr!(ora, abx, 4),
/* 1E */ Option::None, /* 1E */ instr!(asl, abx, 7),
/* 1F */ Option::None, /* 1F */ Option::None,
/* 20 */ instr!(jsr, abs, 6), /* 20 */ instr!(jsr, abs, 6),
@ -570,24 +574,24 @@ pub static INSTRUCTION_SET: [Option<Instruction>; 256] = [
/* 31 */ instr!(and, idy, 5), /* 31 */ instr!(and, idy, 5),
/* 32 */ Option::None, /* 32 */ Option::None,
/* 33 */ Option::None, /* 33 */ Option::None,
/* 34 */ Option::None, /* 34 */ instr!(nop, zpx, 4, true),
/* 35 */ Option::None, /* 35 */ instr!(and, zpx, 4),
/* 36 */ Option::None, /* 36 */ instr!(rol, zpx, 6),
/* 37 */ Option::None, /* 37 */ Option::None,
/* 38 */ instr!(sec, imp, 2), /* 38 */ instr!(sec, imp, 2),
/* 39 */ Option::None, /* 39 */ instr!(and, aby, 4),
/* 3A */ Option::None, /* 3A */ instr!(nop, imp, 2, true),
/* 3B */ Option::None, /* 3B */ Option::None,
/* 3C */ Option::None, /* 3C */ instr!(nop, abx, 4, true),
/* 3D */ Option::None, /* 3D */ instr!(and, abx, 4),
/* 3E */ Option::None, /* 3E */ instr!(rol, abx, 7),
/* 3F */ Option::None, /* 3F */ Option::None,
/* 40 */ instr!(rti, imp, 6), /* 40 */ instr!(rti, imp, 6),
/* 41 */ instr!(eor, idx, 6), /* 41 */ instr!(eor, idx, 6),
/* 42 */ Option::None, /* 42 */ Option::None,
/* 43 */ Option::None, /* 43 */ Option::None,
/* 44 */ Option::None, /* 44 */ instr!(nop, zpg, 3, true),
/* 45 */ instr!(eor, zpg, 3), /* 45 */ instr!(eor, zpg, 3),
/* 46 */ instr!(lsr, zpg, 5), /* 46 */ instr!(lsr, zpg, 5),
/* 47 */ Option::None, /* 47 */ Option::None,
@ -604,24 +608,24 @@ pub static INSTRUCTION_SET: [Option<Instruction>; 256] = [
/* 51 */ instr!(eor, idy, 5), /* 51 */ instr!(eor, idy, 5),
/* 52 */ Option::None, /* 52 */ Option::None,
/* 53 */ Option::None, /* 53 */ Option::None,
/* 54 */ Option::None, /* 54 */ instr!(nop, zpx, 4, true),
/* 55 */ Option::None, /* 55 */ instr!(eor, zpx, 4),
/* 56 */ Option::None, /* 56 */ instr!(lsr, zpx, 6),
/* 57 */ Option::None, /* 57 */ Option::None,
/* 58 */ Option::None, /* 58 */ Option::None,
/* 59 */ Option::None, /* 59 */ instr!(eor, aby, 4),
/* 5A */ Option::None, /* 5A */ instr!(nop, imp, 2, true),
/* 5B */ Option::None, /* 5B */ Option::None,
/* 5C */ Option::None, /* 5C */ instr!(nop, abx, 4, true),
/* 5D */ Option::None, /* 5D */ instr!(eor, abx, 4),
/* 5E */ Option::None, /* 5E */ instr!(lsr, abx, 7),
/* 5F */ Option::None, /* 5F */ Option::None,
/* 60 */ instr!(rts, imp, 6), /* 60 */ instr!(rts, imp, 6),
/* 61 */ instr!(adc, idx, 6), /* 61 */ instr!(adc, idx, 6),
/* 62 */ Option::None, /* 62 */ Option::None,
/* 63 */ Option::None, /* 63 */ Option::None,
/* 64 */ Option::None, /* 64 */ instr!(nop, zpg, 3, true),
/* 65 */ instr!(adc, zpg, 3), /* 65 */ instr!(adc, zpg, 3),
/* 66 */ instr!(ror, zpg, 5), /* 66 */ instr!(ror, zpg, 5),
/* 67 */ Option::None, /* 67 */ Option::None,
@ -638,29 +642,29 @@ pub static INSTRUCTION_SET: [Option<Instruction>; 256] = [
/* 71 */ instr!(adc, idy, 5), /* 71 */ instr!(adc, idy, 5),
/* 72 */ Option::None, /* 72 */ Option::None,
/* 73 */ Option::None, /* 73 */ Option::None,
/* 74 */ Option::None, /* 74 */ instr!(nop, zpx, 4, true),
/* 75 */ Option::None, /* 75 */ instr!(adc, zpx, 4),
/* 76 */ Option::None, /* 76 */ instr!(ror, zpx, 6),
/* 77 */ Option::None, /* 77 */ Option::None,
/* 78 */ instr!(sei, imp, 2), /* 78 */ instr!(sei, imp, 2),
/* 79 */ Option::None, /* 79 */ instr!(adc, aby, 4),
/* 7A */ Option::None, /* 7A */ instr!(nop, imp, 2, true),
/* 7B */ Option::None, /* 7B */ Option::None,
/* 7C */ Option::None, /* 7C */ instr!(nop, abx, 4, true),
/* 7D */ Option::None, /* 7D */ instr!(adc, abx, 4),
/* 7E */ Option::None, /* 7E */ instr!(ror, abx, 7),
/* 7F */ Option::None, /* 7F */ Option::None,
/* 80 */ Option::None, /* 80 */ instr!(nop, imm, 2, true),
/* 81 */ instr!(sta, idx, 6), /* 81 */ instr!(sta, idx, 6),
/* 82 */ Option::None, /* 82 */ instr!(nop, imm, 2, true),
/* 83 */ Option::None, /* 83 */ Option::None,
/* 84 */ instr!(sty, zpg, 3), /* 84 */ instr!(sty, zpg, 3),
/* 85 */ instr!(sta, zpg, 3), /* 85 */ instr!(sta, zpg, 3),
/* 86 */ instr!(stx, zpg, 3), /* 86 */ instr!(stx, zpg, 3),
/* 87 */ Option::None, /* 87 */ Option::None,
/* 88 */ instr!(dey, imp, 2), /* 88 */ instr!(dey, imp, 2),
/* 89 */ Option::None, /* 89 */ instr!(nop, imm, 2, true),
/* 8A */ instr!(txa, imp, 2), /* 8A */ instr!(txa, imp, 2),
/* 8B */ Option::None, /* 8B */ Option::None,
/* 8C */ instr!(sty, abs, 4), /* 8C */ instr!(sty, abs, 4),
@ -672,16 +676,16 @@ pub static INSTRUCTION_SET: [Option<Instruction>; 256] = [
/* 91 */ instr!(sta, idy, 6), /* 91 */ instr!(sta, idy, 6),
/* 92 */ Option::None, /* 92 */ Option::None,
/* 93 */ Option::None, /* 93 */ Option::None,
/* 94 */ Option::None, /* 94 */ instr!(sty, zpx, 4),
/* 95 */ Option::None, /* 95 */ instr!(sta, zpx, 4),
/* 96 */ Option::None, /* 96 */ instr!(stx, zpy, 4),
/* 97 */ Option::None, /* 97 */ Option::None,
/* 98 */ instr!(tya, imp, 2), /* 98 */ instr!(tya, imp, 2),
/* 99 */ Option::None, /* 99 */ instr!(sta, aby, 5),
/* 9A */ instr!(txs, imp, 2), /* 9A */ instr!(txs, imp, 2),
/* 9B */ Option::None, /* 9B */ Option::None,
/* 9C */ Option::None, /* 9C */ Option::None,
/* 9D */ Option::None, /* 9D */ instr!(sta, abx, 5),
/* 9E */ Option::None, /* 9E */ Option::None,
/* 9F */ Option::None, /* 9F */ Option::None,
@ -706,22 +710,22 @@ pub static INSTRUCTION_SET: [Option<Instruction>; 256] = [
/* B1 */ instr!(lda, idy, 5), /* B1 */ instr!(lda, idy, 5),
/* B2 */ Option::None, /* B2 */ Option::None,
/* B3 */ Option::None, /* B3 */ Option::None,
/* B4 */ Option::None, /* B4 */ instr!(ldy, zpx, 4),
/* B5 */ Option::None, /* B5 */ instr!(lda, zpx, 4),
/* B6 */ Option::None, /* B6 */ instr!(ldx, zpy, 4),
/* B7 */ Option::None, /* B7 */ Option::None,
/* B8 */ instr!(clv, imp, 2), /* B8 */ instr!(clv, imp, 2),
/* B9 */ instr!(lda, aby, 4), /* B9 */ instr!(lda, aby, 4),
/* BA */ instr!(tsx, imp, 2), /* BA */ instr!(tsx, imp, 2),
/* BB */ Option::None, /* BB */ Option::None,
/* BC */ Option::None, /* BC */ instr!(ldy, abx, 4),
/* BD */ Option::None, /* BD */ instr!(lda, abx, 4),
/* BE */ Option::None, /* BE */ instr!(ldx, aby, 4),
/* BF */ Option::None, /* BF */ Option::None,
/* C0 */ instr!(cpy, imm, 2), /* C0 */ instr!(cpy, imm, 2),
/* C1 */ instr!(cmp, idx, 6), /* C1 */ instr!(cmp, idx, 6),
/* C2 */ Option::None, /* C2 */ instr!(nop, imm, 2, true),
/* C3 */ Option::None, /* C3 */ Option::None,
/* C4 */ instr!(cpy, zpg, 3), /* C4 */ instr!(cpy, zpg, 3),
/* C5 */ instr!(cmp, zpg, 3), /* C5 */ instr!(cmp, zpg, 3),
@ -740,22 +744,22 @@ pub static INSTRUCTION_SET: [Option<Instruction>; 256] = [
/* D1 */ instr!(cmp, idy, 5), /* D1 */ instr!(cmp, idy, 5),
/* D2 */ Option::None, /* D2 */ Option::None,
/* D3 */ Option::None, /* D3 */ Option::None,
/* D4 */ Option::None, /* D4 */ instr!(nop, zpx, 4, true),
/* D5 */ Option::None, /* D5 */ instr!(cmp, zpx, 4),
/* D6 */ Option::None, /* D6 */ instr!(dec, zpx, 6),
/* D7 */ Option::None, /* D7 */ Option::None,
/* D8 */ instr!(cld, imp, 2), /* D8 */ instr!(cld, imp, 2),
/* D9 */ Option::None, /* D9 */ instr!(cmp, aby, 4),
/* DA */ Option::None, /* DA */ instr!(nop, imp, 2, true),
/* DB */ Option::None, /* DB */ Option::None,
/* DC */ Option::None, /* DC */ instr!(nop, abx, 4, true),
/* DD */ Option::None, /* DD */ instr!(cmp, abx, 4),
/* DE */ Option::None, /* DE */ instr!(dec, abx, 7),
/* DF */ Option::None, /* DF */ Option::None,
/* E0 */ instr!(cpx, imm, 2), /* E0 */ instr!(cpx, imm, 2),
/* E1 */ instr!(sbc, idx, 6), /* E1 */ instr!(sbc, idx, 6),
/* E2 */ Option::None, /* E2 */ instr!(nop, imm, 2, true),
/* E3 */ Option::None, /* E3 */ Option::None,
/* E4 */ instr!(cpx, zpg, 3), /* E4 */ instr!(cpx, zpg, 3),
/* E5 */ instr!(sbc, zpg, 3), /* E5 */ instr!(sbc, zpg, 3),
@ -774,16 +778,16 @@ pub static INSTRUCTION_SET: [Option<Instruction>; 256] = [
/* F1 */ instr!(sbc, idy, 5), /* F1 */ instr!(sbc, idy, 5),
/* F2 */ Option::None, /* F2 */ Option::None,
/* F3 */ Option::None, /* F3 */ Option::None,
/* F4 */ Option::None, /* F4 */ instr!(nop, zpx, 4, true),
/* F5 */ Option::None, /* F5 */ instr!(sbc, zpx, 4),
/* F6 */ Option::None, /* F6 */ instr!(inc, zpx, 6),
/* F7 */ Option::None, /* F7 */ Option::None,
/* F8 */ instr!(sed, imp, 2), /* F8 */ instr!(sed, imp, 2),
/* F9 */ Option::None, /* F9 */ instr!(sbc, aby, 4),
/* FA */ Option::None, /* FA */ instr!(nop, imp, 2, true),
/* FB */ Option::None, /* FB */ Option::None,
/* FC */ Option::None, /* FC */ instr!(nop, abx, 4, true),
/* FD */ Option::None, /* FD */ instr!(sbc, abx, 4),
/* FE */ Option::None, /* FE */ instr!(inc, abx, 7),
/* FF */ Option::None /* FF */ Option::None
]; ];