Added 10 more opcodes into the CPU interpreter
This commit is contained in:
+89
-4
@@ -99,6 +99,16 @@ impl Cpu {
|
||||
0x4C => self.jmp_abs(bus),
|
||||
0xA2 => self.ldx_imm(bus),
|
||||
0x86 => self.stx_zp(bus),
|
||||
0x20 => self.jsr_abs(bus),
|
||||
0x60 => self.rts_imp(bus),
|
||||
0x48 => self.pha_imp(bus),
|
||||
0x68 => self.pla_imp(bus),
|
||||
0x08 => self.php_imp(bus),
|
||||
0x28 => self.plp_imp(bus),
|
||||
0x40 => self.rti_imp(bus),
|
||||
0x00 => self.brk_imp(bus),
|
||||
0xEA => self.nop_imp(bus),
|
||||
0x38 => self.sec_imp(bus),
|
||||
_ => panic!("illegal/unkown opcode {opcode:#04X} at {:#06X}", self.pc.wrapping_sub(1)),
|
||||
};
|
||||
self.cycles += cycles as u64;
|
||||
@@ -182,30 +192,105 @@ impl Cpu {
|
||||
}
|
||||
|
||||
// NES 6502 opcode -> functions
|
||||
fn jmp_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x4C, 3 cycles
|
||||
fn jmp_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x4C, 3 bytes, 3 cycles
|
||||
self.pc = self.fetch16(bus);
|
||||
3
|
||||
}
|
||||
|
||||
fn ldx_imm(&mut self, bus: &mut impl Bus) -> u8 { // 0xA2, 2 cycles
|
||||
fn ldx_imm(&mut self, bus: &mut impl Bus) -> u8 { // 0xA2, 2 bytes, 2 cycles
|
||||
self.x = self.fetch(bus);
|
||||
self.set_zp_flags(self.x);
|
||||
2
|
||||
}
|
||||
|
||||
fn stx_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0x86, 3 cycles
|
||||
fn stx_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0x86, 2 bytes, 3 cycles
|
||||
let (addr, _) = self.address_zp(bus);
|
||||
self.write(bus, addr, self.x);
|
||||
3
|
||||
}
|
||||
|
||||
fn jsr_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x20, 3 bytes, 6 cycles
|
||||
let target = self.fetch16(bus);
|
||||
let ret = self.pc.wrapping_sub(1);
|
||||
self.push(bus, (ret >> 8) as u8);
|
||||
self.push(bus, (ret &0xFF) as u8);
|
||||
self.pc = target;
|
||||
6
|
||||
}
|
||||
|
||||
fn rts_imp(&mut self, bus: &mut impl Bus) -> u8 { // 0x60, 1 byte, 6 cycles
|
||||
let low = self.pop(bus) as u16;
|
||||
let high = self.pop(bus) as u16;
|
||||
self.pc = (high << 8 | low).wrapping_add(1);
|
||||
6
|
||||
}
|
||||
|
||||
fn pha_imp(&mut self, bus: &mut impl Bus) -> u8 { // 0x48, 1 byte, 3 cycles
|
||||
self.push(bus, self.a);
|
||||
3
|
||||
}
|
||||
|
||||
fn pla_imp(&mut self, bus: &mut impl Bus) -> u8 { // 0x68, 1 byte, 4 cycles
|
||||
self.a = self.pop(bus);
|
||||
self.set_zp_flags(self.a);
|
||||
4
|
||||
}
|
||||
|
||||
fn php_imp(&mut self, bus: &mut impl Bus) -> u8 { // 0x08, 1 byte, 3 cycles; B-flag model: B exists only in the pushed copy
|
||||
self.push(bus, self.p | FLAG_BREAK);
|
||||
3
|
||||
}
|
||||
|
||||
fn plp_imp(&mut self, bus: &mut impl Bus) -> u8 { // 0x28, 1 byte, 4 cycles
|
||||
self.p = (self.pop(bus) & !FLAG_BREAK) | FLAG_UNUSED;
|
||||
4
|
||||
}
|
||||
|
||||
fn rti_imp(&mut self, bus: &mut impl Bus) -> u8 { // 0x40, 1 byte, 6 cycles
|
||||
self.p = (self.pop(bus) & !FLAG_BREAK) | FLAG_UNUSED;
|
||||
let low: u16 = self.pop(bus) as u16;
|
||||
let high: u16 = self.pop(bus) as u16;
|
||||
self.pc = high << 8 | low;
|
||||
6
|
||||
}
|
||||
|
||||
fn brk_imp(&mut self, bus: &mut impl Bus) -> u8 { // 0x00, 1 byte, 7 cycles
|
||||
self.pc = self.pc.wrapping_add(1); // Skip padding byte
|
||||
let ret = self.pc;
|
||||
self.push(bus, (ret >> 8) as u8);
|
||||
self.push(bus, (ret & 0xFF) as u8);
|
||||
self.push(bus, self.p | FLAG_BREAK);
|
||||
self.set_flag(FLAG_INTERRUPT);
|
||||
self.pc = self.read16(bus, 0xFFFE); // IRQ vector
|
||||
7
|
||||
}
|
||||
|
||||
fn nop_imp(&mut self, _bus: &mut impl Bus) -> u8 { // 0xEA, 1 byte, 2 cycles
|
||||
2
|
||||
}
|
||||
|
||||
fn sec_imp(&mut self, _bus: &mut impl Bus) -> u8 { // 0x38, 1 byte, 2 cycles
|
||||
self.set_flag(FLAG_CARRY);
|
||||
2
|
||||
}
|
||||
|
||||
// NES 6502 opcode length table/matcher
|
||||
fn opcode_len(opcode: u8) -> u8 {
|
||||
match opcode {
|
||||
0x4C => 3, // JMP abs
|
||||
0xA2 => 2, // LDX imm
|
||||
0x86 => 2, // STX zp
|
||||
_ => 1, // fallback, would show the invalid/unknown opcode only
|
||||
0x20 => 3, // JSR abs
|
||||
0x60 => 1, // RTS imp
|
||||
0x48 => 1, // PHA imp
|
||||
0x68 => 1, // PLA imp
|
||||
0x08 => 1, // PHP imp
|
||||
0x28 => 1, // PLP imp
|
||||
0x40 => 1, // RTI imp
|
||||
0x00 => 1, // BRK imp
|
||||
0xEA => 1, // NOP
|
||||
0x38 => 1, // SEC imp
|
||||
_ => 1, // fallback, would show the invalid/unknown opcode only not its parameters
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user