From db58681074966c7b16a37e7a3e7bc5959b02b617 Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Mon, 29 Aug 2022 17:30:16 +0200 Subject: [PATCH] turned instruction set into static array --- src/addressing.rs | 17 ++ src/cpu.rs | 367 +++++++++++++++++++++++++++++++++----------- src/instructions.rs | 1 - src/main.rs | 1 + src/mnemonic.rs | 35 +++++ 5 files changed, 334 insertions(+), 87 deletions(-) create mode 100644 src/mnemonic.rs diff --git a/src/addressing.rs b/src/addressing.rs index 340a437..3dbbc9c 100644 --- a/src/addressing.rs +++ b/src/addressing.rs @@ -24,6 +24,23 @@ impl CPU print!("{: <30}", "A"); } + pub fn idx(&mut self) + { + let bus = self.bus.upgrade().unwrap(); + + let mut zpg_addr = bus.borrow().read_cpu(self.pc); + self.pc += 1; + + zpg_addr = zpg_addr.wrapping_add(self.x); + let lo = bus.borrow().read_cpu(zpg_addr as u16) as u16; + let hi = bus.borrow().read_cpu(zpg_addr.wrapping_add(1) as u16) as u16; + + self.absolute_addr = (hi << 8) | lo; + self.fetch_type = FetchType::Mem; + + print!("{: <30}", format!("(${:02X},X) @ [${:02X}] = ${:04X} = {:02X}", zpg_addr.wrapping_sub(self.x), zpg_addr, self.absolute_addr, bus.borrow().read_cpu(self.absolute_addr))); + } + pub fn imm(&mut self) { let bus = self.bus.upgrade().unwrap(); diff --git a/src/cpu.rs b/src/cpu.rs index b0bf005..02caefc 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -1,8 +1,8 @@ use std::cell::RefCell; use std::rc::{Rc, Weak}; -use copystr::s3; use crate::bus::Bus; +use crate::mnemonic::Mnemonic; type InstrFn = fn(&mut CPU); type AddrFn = fn(&mut CPU); @@ -15,7 +15,7 @@ struct Instruction cycles: u8, length: u8, - name: s3 + name: Mnemonic } macro_rules! instr @@ -29,7 +29,7 @@ macro_rules! instr cycles: $cyc, length: $len, - name: s3::new(stringify!($instr)).unwrap() + name: Mnemonic::new(stringify!($instr), false) }) } } @@ -57,90 +57,12 @@ pub struct CPU pub pc: u16, pub bus: Weak>, - - instruction_set: [Option; 256] } impl CPU { pub fn new(bus: &Rc>) -> CPU { - const UNDEF_INSTR: Option = None; - let mut instr_set = [UNDEF_INSTR; 256]; - - instr_set[0x08] = instr!(php, imp, 3, 1); - instr_set[0x09] = instr!(ora, imm, 2, 2); - instr_set[0x0A] = instr!(asl, acc, 2, 1); - - instr_set[0x10] = instr!(bpl, rel, 2, 2); - instr_set[0x18] = instr!(clc, imp, 2, 1); - - instr_set[0x20] = instr!(jsr, abs, 6, 3); - instr_set[0x24] = instr!(bit, zpg, 3, 2); - instr_set[0x28] = instr!(plp, imp, 4, 1); - instr_set[0x29] = instr!(and, imm, 2, 2); - instr_set[0x2A] = instr!(rol, acc, 2, 1); - - instr_set[0x30] = instr!(bmi, rel, 2, 2); - instr_set[0x38] = instr!(sec, imp, 2, 1); - - instr_set[0x40] = instr!(rti, imp, 6, 1); - instr_set[0x4A] = instr!(lsr, acc, 2, 1); - instr_set[0x48] = instr!(pha, imp, 3, 1); - instr_set[0x49] = instr!(eor, imm, 2, 2); - instr_set[0x4C] = instr!(jmp, abs, 3, 3); - - instr_set[0x50] = instr!(bvc, rel, 2, 2); - - instr_set[0x60] = instr!(rts, imp, 6, 1); - instr_set[0x68] = instr!(pla, imp, 4, 1); - instr_set[0x69] = instr!(adc, imm, 2, 2); - instr_set[0x6A] = instr!(ror, acc, 2, 1); - - instr_set[0x70] = instr!(bvs, rel, 2, 2); - instr_set[0x78] = instr!(sei, imp, 2, 1); - - instr_set[0x84] = instr!(sty, zpg, 3, 2); - instr_set[0x85] = instr!(sta, zpg, 3, 2); - instr_set[0x86] = instr!(stx, zpg, 3, 2); - instr_set[0x88] = instr!(dey, imp, 2, 1); - instr_set[0x8A] = instr!(txa, imp, 2, 1); - instr_set[0x8D] = instr!(sta, abs, 4, 3); - instr_set[0x8E] = instr!(stx, abs, 4, 3); - - instr_set[0x90] = instr!(bcc, rel, 2, 2); - instr_set[0x98] = instr!(tya, imp, 2, 1); - instr_set[0x9A] = instr!(txs, imp, 2, 1); - - instr_set[0xA0] = instr!(ldy, imm, 2, 2); - instr_set[0xA2] = instr!(ldx, imm, 2, 2); - instr_set[0xA5] = instr!(lda, zpg, 3, 2); - instr_set[0xA8] = instr!(tay, imp, 2, 1); - instr_set[0xA9] = instr!(lda, imm, 2, 2); - instr_set[0xAA] = instr!(tax, imp, 2, 1); - instr_set[0xAD] = instr!(lda, abs, 4, 3); - instr_set[0xAE] = instr!(ldx, abs, 4, 3); - - instr_set[0xB0] = instr!(bcs, rel, 2, 2); - instr_set[0xB8] = instr!(clv, imp, 2, 1); - instr_set[0xBA] = instr!(tsx, imp, 2, 1); - - instr_set[0xC0] = instr!(cpy, imm, 2, 2); - instr_set[0xC8] = instr!(iny, imp, 2, 1); - instr_set[0xC9] = instr!(cmp, imm, 2, 2); - instr_set[0xCA] = instr!(dex, imp, 2, 1); - - instr_set[0xD0] = instr!(bne, rel, 2, 2); - instr_set[0xD8] = instr!(cld, imp, 2, 1); - - instr_set[0xE0] = instr!(cpx, imm, 2, 2); - instr_set[0xE8] = instr!(inx, imp, 2, 1); - instr_set[0xE9] = instr!(sbc, imm, 2, 2); - instr_set[0xEA] = instr!(nop, imp, 2, 1); - - instr_set[0xF0] = instr!(beq, rel, 2, 2); - instr_set[0xF8] = instr!(sed, imp, 2, 1); - CPU { cycle: 0, total_cycles: 0, @@ -157,9 +79,7 @@ impl CPU pc: 0, - bus: Rc::downgrade(bus), - - instruction_set: instr_set + bus: Rc::downgrade(bus) } } @@ -198,7 +118,7 @@ impl CPU { let bus = self.bus.upgrade().unwrap(); let opcode: u8 = bus.borrow().read_cpu(self.pc); - let instr = self.instruction_set[opcode as usize].expect(&format!("Unimplemented opcode {:02X}", opcode)); + let instr = INSTRUCTION_SET[opcode as usize].expect(&format!("Unimplemented opcode {:02X}", opcode)); print!("{:04X} ", self.pc); for byte in 0..3 @@ -224,4 +144,279 @@ impl CPU 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); } -} \ No newline at end of file + +} + +static INSTRUCTION_SET: [Option; 256] = [ + /* 00 */ Option::None, + /* 01 */ instr!(ora, idx, 6, 2), + /* 02 */ Option::None, + /* 03 */ Option::None, + /* 04 */ Option::None, + /* 05 */ Option::None, + /* 06 */ Option::None, + /* 07 */ Option::None, + /* 08 */ instr!(php, imp, 3, 1), + /* 09 */ instr!(ora, imm, 2, 2), + /* 0A */ instr!(asl, acc, 2, 1), + /* 0B */ Option::None, + /* 0C */ Option::None, + /* 0D */ Option::None, + /* 0E */ Option::None, + /* 0F */ Option::None, + + /* 10 */ instr!(bpl, rel, 2, 2), + /* 11 */ Option::None, + /* 12 */ Option::None, + /* 13 */ Option::None, + /* 14 */ Option::None, + /* 15 */ Option::None, + /* 16 */ Option::None, + /* 17 */ Option::None, + /* 18 */ instr!(clc, imp, 2, 1), + /* 09 */ Option::None, + /* 0A */ Option::None, + /* 0B */ Option::None, + /* 0C */ Option::None, + /* 0D */ Option::None, + /* 0E */ Option::None, + /* 0F */ Option::None, + + /* 20 */ instr!(jsr, abs, 6, 3), + /* 21 */ instr!(and, idx, 6, 2), + /* 22 */ Option::None, + /* 23 */ Option::None, + /* 24 */ instr!(bit, zpg, 3, 2), + /* 25 */ Option::None, + /* 26 */ Option::None, + /* 27 */ Option::None, + /* 28 */ instr!(plp, imp, 4, 1), + /* 29 */ instr!(and, imm, 2, 2), + /* 2A */ instr!(rol, acc, 2, 1), + /* 2B */ Option::None, + /* 2C */ Option::None, + /* 2D */ Option::None, + /* 2E */ Option::None, + /* 2F */ Option::None, + + /* 30 */ instr!(bmi, rel, 2, 2), + /* 31 */ Option::None, + /* 32 */ Option::None, + /* 33 */ Option::None, + /* 34 */ Option::None, + /* 35 */ Option::None, + /* 36 */ Option::None, + /* 37 */ Option::None, + /* 38 */ instr!(sec, imp, 2, 1), + /* 39 */ Option::None, + /* 3A */ Option::None, + /* 3B */ Option::None, + /* 3C */ Option::None, + /* 3D */ Option::None, + /* 3E */ Option::None, + /* 3F */ Option::None, + + /* 40 */ instr!(rti, imp, 6, 1), + /* 41 */ instr!(eor, idx, 6, 2), + /* 42 */ Option::None, + /* 43 */ Option::None, + /* 44 */ Option::None, + /* 45 */ Option::None, + /* 46 */ Option::None, + /* 47 */ Option::None, + /* 48 */ instr!(pha, imp, 3, 1), + /* 49 */ instr!(eor, imm, 2, 2), + /* 4A*/ instr!(lsr, acc, 2, 1), + /* 4B */ Option::None, + /* 4C */ instr!(jmp, abs, 3, 3), + /* 4D */ Option::None, + /* 4E */ Option::None, + /* 4F */ Option::None, + + /* 50 */ instr!(bvc, rel, 2, 2), + /* 51 */ Option::None, + /* 52 */ Option::None, + /* 53 */ Option::None, + /* 54 */ Option::None, + /* 55 */ Option::None, + /* 56 */ Option::None, + /* 57 */ Option::None, + /* 58 */ Option::None, + /* 59 */ Option::None, + /* 5A */ Option::None, + /* 5B */ Option::None, + /* 5C */ Option::None, + /* 5D */ Option::None, + /* 5E */ Option::None, + /* 5F */ Option::None, + + /* 60 */ instr!(rts, imp, 6, 1), + /* 61 */ instr!(adc, idx, 6, 2), + /* 62 */ Option::None, + /* 63 */ Option::None, + /* 64 */ Option::None, + /* 65 */ Option::None, + /* 66 */ Option::None, + /* 67 */ Option::None, + /* 68 */ instr!(pla, imp, 4, 1), + /* 69 */ instr!(adc, imm, 2, 2), + /* 6A */ instr!(ror, acc, 2, 1), + /* 6B */ Option::None, + /* 6C */ Option::None, + /* 6D */ Option::None, + /* 6E */ Option::None, + /* 6F */ Option::None, + + /* 70 */ instr!(bvs, rel, 2, 2), + /* 71 */ Option::None, + /* 72 */ Option::None, + /* 73 */ Option::None, + /* 74 */ Option::None, + /* 75 */ Option::None, + /* 76 */ Option::None, + /* 77 */ Option::None, + /* 78 */ instr!(sei, imp, 2, 1), + /* 79 */ Option::None, + /* 7A */ Option::None, + /* 7B */ Option::None, + /* 7C */ Option::None, + /* 7D */ Option::None, + /* 7E */ Option::None, + /* 7F */ Option::None, + + /* 80 */ Option::None, + /* 81 */ instr!(sta, idx, 6, 2), + /* 82 */ Option::None, + /* 83 */ Option::None, + /* 84 */ instr!(sty, zpg, 3, 2), + /* 85 */ instr!(sta, zpg, 3, 2), + /* 86 */ instr!(stx, zpg, 3, 2), + /* 87 */ Option::None, + /* 88 */ instr!(dey, imp, 2, 1), + /* 89 */ Option::None, + /* 8A */ instr!(txa, imp, 2, 1), + /* 8B */ Option::None, + /* 8C */ Option::None, + /* 8D */ instr!(sta, abs, 4, 3), + /* 8E */ instr!(stx, abs, 4, 3), + /* 8F */ Option::None, + + /* 90 */ instr!(bcc, rel, 2, 2), + /* 91 */ Option::None, + /* 92 */ Option::None, + /* 93 */ Option::None, + /* 94 */ Option::None, + /* 95 */ Option::None, + /* 96 */ Option::None, + /* 97 */ Option::None, + /* 98 */ instr!(tya, imp, 2, 1), + /* 99 */ Option::None, + /* 9A */ instr!(txs, imp, 2, 1), + /* 9B */ Option::None, + /* 9C */ Option::None, + /* 9D */ Option::None, + /* 9E */ Option::None, + /* 9F */ Option::None, + + /* A0 */ instr!(ldy, imm, 2, 2), + /* A1 */ instr!(lda, idx, 6, 2), + /* A2 */ instr!(ldx, imm, 2, 2), + /* A3 */ Option::None, + /* A4 */ instr!(ldy, zpg, 3, 2), + /* A5 */ instr!(lda, zpg, 3, 2), + /* A6 */ instr!(ldx, zpg, 3, 2), + /* A7 */ Option::None, + /* A8 */ instr!(tay, imp, 2, 1), + /* A9 */ instr!(lda, imm, 2, 2), + /* AA */ instr!(tax, imp, 2, 1), + /* AB */ Option::None, + /* AC */ Option::None, + /* AD */ instr!(lda, abs, 4, 3), + /* AE */ instr!(ldx, abs, 4, 3), + /* AF */ Option::None, + + /* B0 */ instr!(bcs, rel, 2, 2), + /* B1 */ Option::None, + /* B2 */ Option::None, + /* B3 */ Option::None, + /* B4 */ Option::None, + /* B5 */ Option::None, + /* B6 */ Option::None, + /* B7 */ Option::None, + /* B8 */ instr!(clv, imp, 2, 1), + /* B9 */ Option::None, + /* BA */ instr!(tsx, imp, 2, 1), + /* BB */ Option::None, + /* BC */ Option::None, + /* BD */ Option::None, + /* BE */ Option::None, + /* BF */ Option::None, + + /* C0 */ instr!(cpy, imm, 2, 2), + /* C1 */ instr!(cmp, idx, 6, 2), + /* C2 */ Option::None, + /* C3 */ Option::None, + /* C4 */ Option::None, + /* C5 */ Option::None, + /* C6 */ Option::None, + /* C7 */ Option::None, + /* C8 */ instr!(iny, imp, 2, 1), + /* C9 */ instr!(cmp, imm, 2, 2), + /* CA */ instr!(dex, imp, 2, 1), + /* CB */ Option::None, + /* CC */ Option::None, + /* CD */ Option::None, + /* CE */ Option::None, + /* CF */ Option::None, + + /* D0 */ instr!(bne, rel, 2, 2), + /* D1 */ Option::None, + /* D2 */ Option::None, + /* D3 */ Option::None, + /* D4 */ Option::None, + /* D5 */ Option::None, + /* D6 */ Option::None, + /* D7 */ Option::None, + /* D8 */ instr!(cld, imp, 2, 1), + /* D9 */ Option::None, + /* DA */ Option::None, + /* DB */ Option::None, + /* DC */ Option::None, + /* DD */ Option::None, + /* DE */ Option::None, + /* DF */ Option::None, + + /* E0 */ instr!(cpx, imm, 2, 2), + /* E1 */ instr!(sbc, idx, 6, 2), + /* E2 */ Option::None, + /* E3 */ Option::None, + /* E4 */ Option::None, + /* E5 */ Option::None, + /* E6 */ Option::None, + /* E7 */ Option::None, + /* E8 */ instr!(inx, imp, 2, 1), + /* E9 */ instr!(sbc, imm, 2, 2), + /* EA */ instr!(nop, imp, 2, 1), + /* EB */ Option::None, + /* EC */ Option::None, + /* ED */ Option::None, + /* EE */ Option::None, + /* EF */ Option::None, + + /* F0 */ instr!(beq, rel, 2, 2), + /* F1 */ Option::None, + /* F2 */ Option::None, + /* F3 */ Option::None, + /* F4 */ Option::None, + /* F5 */ Option::None, + /* F6 */ Option::None, + /* F7 */ Option::None, + /* F8 */ instr!(sed, imp, 2, 1), + /* F9 */ Option::None, + /* FA */ Option::None, + /* FB */ Option::None, + /* FC */ Option::None, + /* FD */ Option::None, + /* FE */ Option::None, + /* FF */ Option::None +]; \ No newline at end of file diff --git a/src/instructions.rs b/src/instructions.rs index 7e618ea..c96762d 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -325,7 +325,6 @@ impl CPU bitshift_fn!(rol, <<, true); bitshift_fn!(ror, >>, true); - pub fn adc(&mut self) { let value = self.fetch() as u16; diff --git a/src/main.rs b/src/main.rs index 08748ac..160e09f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ mod cpu; mod instructions; mod addressing; mod cartridge; +mod mnemonic; use nes::NES; diff --git a/src/mnemonic.rs b/src/mnemonic.rs new file mode 100644 index 0000000..42f6932 --- /dev/null +++ b/src/mnemonic.rs @@ -0,0 +1,35 @@ +use std::fmt; + +#[derive(Copy, Clone)] +pub struct Mnemonic { + buf: [char; 4] +} + +impl Mnemonic +{ + pub const fn new(content: &str, illegal: bool) -> Mnemonic + { + let mut buf: [char; 4] = [' '; 4]; + if illegal { + buf[0] = '*'; + } else { + buf[0] = ' '; + } + + buf[1] = content.as_bytes()[0] as char; + buf[2] = content.as_bytes()[1] as char; + buf[3] = content.as_bytes()[2] as char; + + Mnemonic { + buf: buf + } + } +} + +impl fmt::Display for Mnemonic +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result + { + write!(f, "{}{}{}{}", self.buf[0], self.buf[1], self.buf[2], self.buf[3]) + } +} \ No newline at end of file