implemented the ORA, ANd and EOR family of instructions
This commit is contained in:
+179
-8
@@ -97,17 +97,17 @@ impl Cpu {
|
||||
let opcode: u8 = self.fetch(bus);
|
||||
let cycles = match opcode {
|
||||
// Jumps & subroutines
|
||||
0x4C => self.jmp_abs(bus), 0x20 => self.jsr_abs(bus), 0x60 => self.rts_imp(bus),
|
||||
0x4C => self.jmp_abs(bus), 0x20 => self.jsr_abs(bus), 0x60 => self.rts_imp(bus),
|
||||
0x40 => self.rti_imp(bus), 0x00 => self.brk_imp(bus),
|
||||
// Stack
|
||||
0x48 => self.pha_imp(bus), 0x68 => self.pla_imp(bus), 0x08 => self.php_imp(bus),
|
||||
0x48 => self.pha_imp(bus), 0x68 => self.pla_imp(bus), 0x08 => self.php_imp(bus),
|
||||
0x28 => self.plp_imp(bus),
|
||||
// Flags & misc
|
||||
0x38 => self.sec_imp(bus), 0x18 => self.clc_imp(bus), 0x58 => self.cli_imp(bus),
|
||||
0x78 => self.sei_imp(bus), 0xD8 => self.cld_imp(bus), 0xF8 => self.sed_imp(bus),
|
||||
0x38 => self.sec_imp(bus), 0x18 => self.clc_imp(bus), 0x58 => self.cli_imp(bus),
|
||||
0x78 => self.sei_imp(bus), 0xD8 => self.cld_imp(bus), 0xF8 => self.sed_imp(bus),
|
||||
0xB8 => self.clv_imp(bus), 0xEA => self.nop_imp(bus),
|
||||
// Branches
|
||||
0x90 => self.bcc_rel(bus), 0xB0 => self.bcs_rel(bus), 0xF0 => self.beq_rel(bus),
|
||||
0x90 => self.bcc_rel(bus), 0xB0 => self.bcs_rel(bus), 0xF0 => self.beq_rel(bus),
|
||||
0xD0 => self.bne_rel(bus), 0x10 => self.bpl_rel(bus), 0x30 => self.bmi_rel(bus),
|
||||
0x50 => self.bvc_rel(bus), 0x70 => self.bvs_rel(bus),
|
||||
// Loads
|
||||
@@ -136,13 +136,25 @@ impl Cpu {
|
||||
0xE5 => self.sbc_zp(bus), 0xF5 => self.sbc_zpx(bus), 0xED => self.sbc_abs(bus),
|
||||
0xFD => self.sbc_abx(bus), 0xF9 => self.sbc_aby(bus), 0xE1 => self.sbc_izx(bus),
|
||||
0xF1 => self.sbc_izy(bus), 0x24 => self.bit_zp(bus), 0x2C => self.bit_abs(bus),
|
||||
// Binary - AND
|
||||
0x29 => self.and_imm(bus), 0x25 => self.and_zp(bus), 0x35 => self.and_zpx(bus),
|
||||
0x2D => self.and_abs(bus), 0x3D => self.and_abx(bus), 0x39 => self.and_aby(bus),
|
||||
0x21 => self.and_izx(bus), 0x31 => self.and_izy(bus),
|
||||
// Binary - ORA
|
||||
0x09 => self.ora_imm(bus), 0x05 => self.ora_zp(bus), 0x15 => self.ora_zpx(bus),
|
||||
0x0D => self.ora_abs(bus), 0x1D => self.ora_abx(bus), 0x19 => self.ora_aby(bus),
|
||||
0x01 => self.ora_izx(bus), 0x11 => self.ora_izy(bus),
|
||||
// Binary - EOR
|
||||
0x49 => self.eor_imm(bus), 0x45 => self.eor_zp(bus), 0x55 => self.eor_zpx(bus),
|
||||
0x4D => self.eor_abs(bus), 0x5D => self.eor_abx(bus), 0x59 => self.eor_aby(bus),
|
||||
0x41 => self.eor_izx(bus), 0x51 => self.eor_izy(bus),
|
||||
_ => panic!("illegal/unkown opcode {opcode:#04X} at {:#06X}", self.pc.wrapping_sub(1)),
|
||||
};
|
||||
self.cycles += cycles as u64;
|
||||
cycles
|
||||
}
|
||||
|
||||
// NES 6502 opcode length table/matcher
|
||||
// NES 6502 opcode length table/matcher; note: this one could be seem as redudant but i like it so deal with it >:3, also it would be used by the GUI later
|
||||
pub fn opcode_len(opcode: u8) -> u8 {
|
||||
match opcode {
|
||||
0x4C => 3, /* JMP abs */ 0xA2 => 2, /* LDX imm */ 0x86 => 2, /* STX zp */ 0x20 => 3, /* JSR abs */
|
||||
@@ -167,6 +179,12 @@ impl Cpu {
|
||||
0x61 => 2, /* ADC izx */ 0x71 => 2, /* ADC izy */ 0xE9 => 2, /* SBC imm */ 0xE5 => 2, /* SBC zp */
|
||||
0xF5 => 2, /* SBC zpx */ 0xED => 3, /* SBC abs */ 0xFD => 3, /* SBC abx */ 0xF9 => 3, /* SBC aby */
|
||||
0xE1 => 2, /* SBC izx */ 0xF1 => 2, /* SBC izy */ 0x24 => 2, /* BIT zp */ 0x2C => 3, /* BIT abs */
|
||||
0x29 => 2, /* AND imm */ 0x25 => 2, /* AND zp */ 0x35 => 2, /* AND zpx */ 0x2D => 3, /* AND abs */
|
||||
0x3D => 3, /* AND abx */ 0x39 => 3, /* AND aby */ 0x21 => 2, /* AND izx */ 0x31 => 2, /* AND izy */
|
||||
0x09 => 2, /* ORA imm */ 0x05 => 2, /* ORA zp */ 0x15 => 2, /* ORA zpx */ 0x0D => 3, /* ORA abs */
|
||||
0x1D => 3, /* ORA abx */ 0x19 => 3, /* ORA aby */ 0x01 => 2, /* ORA izx */ 0x11 => 2, /* ORA izy */
|
||||
0x49 => 2, /* EOR imm */ 0x45 => 2, /* EOR zp */ 0x55 => 2, /* EOR zpx */ 0x4D => 3, /* EOR abs */
|
||||
0x5D => 3, /* EOR abx */ 0x59 => 3, /* EOR aby */ 0x41 => 2, /* EOR izx */ 0x51 => 2, /* EOR izy */
|
||||
_ => 1, // fallback, would show the invalid/unknown opcode only not its parameters
|
||||
}
|
||||
}
|
||||
@@ -234,7 +252,7 @@ impl Cpu {
|
||||
(address, extra)
|
||||
}
|
||||
|
||||
fn address_ind(&mut self, bus: &mut impl Bus) -> (u16, u8) { // used by JMP instruction + hardware bug where the page wraps around
|
||||
fn address_ind(&mut self, bus: &mut impl Bus) -> (u16, u8) { // used by JMP (indirect) instruction + hardware bug where the page wraps around
|
||||
let ptr: u16 = self.fetch16(bus); // pointer itself
|
||||
let low: u16 = self.read(bus, ptr) as u16;
|
||||
let high_ptr: u16 = (ptr & 0xFF00) | (ptr.wrapping_add(1) & 0x00FF); // Hardware bug wrap here
|
||||
@@ -363,6 +381,29 @@ impl Cpu {
|
||||
base + extra
|
||||
}
|
||||
|
||||
// AND core (AND binary operation)
|
||||
fn and(&mut self, bus: &mut impl Bus, (address, extra): (u16, u8), base: u8) -> u8 {
|
||||
let value = self.read(bus, address);
|
||||
self.a &= value;
|
||||
self.set_zp_flags(self.a);
|
||||
base + extra
|
||||
}
|
||||
|
||||
// ORA core (OR binary operation)
|
||||
fn ora(&mut self, bus: &mut impl Bus, (address, extra): (u16, u8), base: u8) -> u8 {
|
||||
let value = self.read(bus, address);
|
||||
self.a |= value;
|
||||
self.set_zp_flags(self.a);
|
||||
base + extra
|
||||
}
|
||||
|
||||
// EOR core (Exclusive-OR binary operation)
|
||||
fn eor(&mut self, bus: &mut impl Bus, (address, extra): (u16, u8), base: u8) -> u8 {
|
||||
let value = self.read(bus, address);
|
||||
self.a ^= value;
|
||||
self.set_zp_flags(self.a);
|
||||
base + extra
|
||||
}
|
||||
|
||||
// NES 6502 opcode -> functions
|
||||
fn jmp_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x4C, 3 bytes, 3 cycles
|
||||
@@ -798,7 +839,137 @@ impl Cpu {
|
||||
2
|
||||
}
|
||||
|
||||
// all branching alternatives here all 1 bytes
|
||||
// AND variants
|
||||
fn and_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0x25, 2 bytes, 3 cycles
|
||||
let (address, extra) = self.address_zp(bus);
|
||||
self.and(bus, (address, extra), 3)
|
||||
}
|
||||
|
||||
fn and_zpx(&mut self, bus: &mut impl Bus) -> u8 { // 0x35, 2 bytes, 4 cycles
|
||||
let (address, extra) = self.address_zpx(bus);
|
||||
self.and(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn and_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x2D, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_abs(bus);
|
||||
self.and(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn and_abx(&mut self, bus: &mut impl Bus) -> u8 { // 0x3D, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_abx(bus);
|
||||
self.and(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn and_aby(&mut self, bus: &mut impl Bus) -> u8 { // 0x39, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_aby(bus);
|
||||
self.and(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn and_izx(&mut self, bus: &mut impl Bus) -> u8 { // 0x21, 2 bytes, 6 cycles
|
||||
let (address, extra) = self.address_izx(bus);
|
||||
self.and(bus, (address, extra), 6)
|
||||
}
|
||||
|
||||
fn and_izy(&mut self, bus: &mut impl Bus) -> u8 { // 0x31, 2 bytes, 5 cycles
|
||||
let (address, extra) = self.address_izy(bus);
|
||||
self.and(bus, (address, extra), 5)
|
||||
}
|
||||
|
||||
// ORA variants
|
||||
fn ora_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0x05, 2 bytes, 3 cycles
|
||||
let (address, extra) = self.address_zp(bus);
|
||||
self.ora(bus, (address, extra), 3)
|
||||
}
|
||||
|
||||
fn ora_zpx(&mut self, bus: &mut impl Bus) -> u8 { // 0x15, 2 bytes, 4 cycles
|
||||
let (address, extra) = self.address_zpx(bus);
|
||||
self.ora(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn ora_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x0D, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_abs(bus);
|
||||
self.ora(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn ora_abx(&mut self, bus: &mut impl Bus) -> u8 { // 0x1D, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_abx(bus);
|
||||
self.ora(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn ora_aby(&mut self, bus: &mut impl Bus) -> u8 { // 0x19, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_aby(bus);
|
||||
self.ora(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn ora_izx(&mut self, bus: &mut impl Bus) -> u8 { // 0x01, 2 bytes, 6 cycles
|
||||
let (address, extra) = self.address_izx(bus);
|
||||
self.ora(bus, (address, extra), 6)
|
||||
}
|
||||
|
||||
fn ora_izy(&mut self, bus: &mut impl Bus) -> u8 { // 0x11, 2 bytes, 5 cycles
|
||||
let (address, extra) = self.address_izy(bus);
|
||||
self.ora(bus, (address, extra), 5)
|
||||
}
|
||||
|
||||
// EOR variants
|
||||
fn eor_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0x45, 2 bytes, 3 cycles
|
||||
let (address, extra) = self.address_zp(bus);
|
||||
self.eor(bus, (address, extra), 3)
|
||||
}
|
||||
|
||||
fn eor_zpx(&mut self, bus: &mut impl Bus) -> u8 { // 0x55, 2 bytes, 4 cycles
|
||||
let (address, extra) = self.address_zpx(bus);
|
||||
self.eor(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn eor_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x4D, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_abs(bus);
|
||||
self.eor(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn eor_abx(&mut self, bus: &mut impl Bus) -> u8 { // 0x5D, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_abx(bus);
|
||||
self.eor(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn eor_aby(&mut self, bus: &mut impl Bus) -> u8 { // 0x59, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_aby(bus);
|
||||
self.eor(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn eor_izx(&mut self, bus: &mut impl Bus) -> u8 { // 0x41, 2 bytes, 6 cycles
|
||||
let (address, extra) = self.address_izx(bus);
|
||||
self.eor(bus, (address, extra), 6)
|
||||
}
|
||||
|
||||
fn eor_izy(&mut self, bus: &mut impl Bus) -> u8 { // 0x51, 2 bytes, 5 cycles
|
||||
let (address, extra) = self.address_izy(bus);
|
||||
self.eor(bus, (address, extra), 5)
|
||||
}
|
||||
|
||||
// AND immediate variant
|
||||
fn and_imm(&mut self, bus: &mut impl Bus) -> u8 { // 0x29, 2 bytes, 2 cycles
|
||||
self.a &= self.fetch(bus);
|
||||
self.set_zp_flags(self.a);
|
||||
2
|
||||
}
|
||||
|
||||
// ORA immediate variant
|
||||
fn ora_imm(&mut self, bus: &mut impl Bus) -> u8 { // 0x09, 2 bytes, 2 cycles
|
||||
self.a |= self.fetch(bus);
|
||||
self.set_zp_flags(self.a);
|
||||
2
|
||||
}
|
||||
|
||||
// EOR immediate variant
|
||||
fn eor_imm(&mut self, bus: &mut impl Bus) -> u8 { // 0x49, 2 bytes, 2 cycles
|
||||
self.a ^= self.fetch(bus);
|
||||
self.set_zp_flags(self.a);
|
||||
2
|
||||
}
|
||||
|
||||
|
||||
// all branching alternatives here, all 1 bytes
|
||||
fn bcs_rel(&mut self, bus: &mut impl Bus) -> u8 { self.branch(bus, self.flag(FLAG_CARRY)) } // 0xB0
|
||||
fn bcc_rel(&mut self, bus: &mut impl Bus) -> u8 { self.branch(bus, !self.flag(FLAG_CARRY)) } // 0x90
|
||||
fn beq_rel(&mut self, bus: &mut impl Bus) -> u8 { self.branch(bus, self.flag(FLAG_ZERO)) } // 0xF0
|
||||
|
||||
Reference in New Issue
Block a user