Skip to content

Commit

Permalink
implement operation - LSR
Browse files Browse the repository at this point in the history
  • Loading branch information
marcantoineg committed Jun 11, 2024
1 parent 14d950c commit c36761e
Show file tree
Hide file tree
Showing 2 changed files with 226 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,12 @@ impl CPU {
(0xAC, Operation::new(LDY, Absolute, 3)),
(0xBC, Operation::new(LDY, AbsoluteX, 3)),

(0x4A, Operation::new(LSR, Implied, 1)),
(0x46, Operation::new(LSR, ZeroPage, 2)),
(0x56, Operation::new(LSR, ZeroPageX, 2)),
(0x4E, Operation::new(LSR, Absolute, 3)),
(0x5E, Operation::new(LSR, AbsoluteX, 3)),

(0xAA, Operation::new(TAX, Implied, 1)),
(0xA8, Operation::new(TAY, Implied, 1)),
]);
Expand Down Expand Up @@ -293,6 +299,7 @@ impl CPU {
LDA => self.lda(op.addressing_mode),
LDX => self.ldx(op.addressing_mode),
LDY => self.ldy(op.addressing_mode),
LSR => self.lsr(op.addressing_mode),
TAX => self.tax(),
TAY => self.tay(),

Expand Down Expand Up @@ -525,6 +532,19 @@ impl CPU {
self.program_counter = subroutine_addr;
}

fn lsr(&mut self, mode: AddressingMode) {
if mode == AddressingMode::Implied {
self.set_carry_flag((self.register_a & 0b0000_0001) != 0);
self.set_register_a(self.register_a >> 1);
} else {
let addr = self.get_op_target_addr(mode);
let mem_value = self.memory.read(addr);

self.set_carry_flag((mem_value & 0b0000_0001) != 0);
self.set_memory(addr, mem_value >> 1);
}
}

fn set_register_a(&mut self, value: u8) {
self.register_a = value;
self.set_zero_flag(self.register_a);
Expand Down
206 changes: 206 additions & 0 deletions tests/lsr_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
use common::assert_flag;
use nes_emulator::cpu::{Flags, CPU};

mod common;
use crate::common::assert_no_flags;

#[test]
fn test_0x4a_lsr_implied_shifts_right_without_carry_correctly() {
let mut cpu = CPU::new();
cpu.register_a = 0b1010_1010;

cpu.load_and_run_without_reset(vec![
0x4A, 0x00
]);

assert_eq!(cpu.register_a, 0b0101_0101);
assert_no_flags(&cpu);
}

#[test]
fn test_0x4a_lsr_implied_shifts_right_with_carry_correctly() {
let mut cpu = CPU::new();
cpu.register_a = 0b1010_1011;

cpu.load_and_run_without_reset(vec![
0x4A, 0x00
]);

assert_eq!(cpu.register_a, 0b0101_0101);
assert_flag(&cpu, Flags::Carry);
}

#[test]
fn test_0x4a_lsr_implied_shifts_right_with_zero_correctly() {
let mut cpu = CPU::new();
cpu.register_a = 0x00;

cpu.load_and_run_without_reset(vec![
0x4A, 0x00
]);

assert_eq!(cpu.register_a, 0x00);
assert_flag(&cpu, Flags::Zero);
}

#[test]
fn test_0x46_lsr_zero_page_shifts_right_without_carry_correctly() {
let mut cpu = CPU::new();
cpu.memory.write(0x0010, 0b1000_1110);

cpu.load_and_run_without_reset(vec![
0x46, 0x10, 0x00
]);

assert_eq!(cpu.memory.read(0x0010), 0b0100_0111);
assert_no_flags(&cpu);
}

#[test]
fn test_0x46_lsr_zero_page_shifts_right_with_carry_correctly() {
let mut cpu = CPU::new();
cpu.memory.write(0x0010, 0b1000_1111);

cpu.load_and_run_without_reset(vec![
0x46, 0x10, 0x00
]);

assert_eq!(cpu.memory.read(0x0010), 0b0100_0111);
assert_flag(&cpu, Flags::Carry)
}

#[test]
fn test_0x46_lsr_zero_page_shifts_right_with_zero_correctly() {
let mut cpu = CPU::new();
cpu.memory.write(0x0010, 0x00);

cpu.load_and_run_without_reset(vec![
0x46, 0x10, 0x00
]);

assert_eq!(cpu.memory.read(0x0010), 0x00);
assert_flag(&cpu, Flags::Zero)
}

#[test]
fn test_0x56_lsr_zero_page_x_shifts_right_without_carry_correctly() {
let mut cpu = CPU::new();
cpu.register_x = 0x01;
cpu.memory.write(0x0011, 0b1000_1110);

cpu.load_and_run_without_reset(vec![
0x56, 0x10, 0x00
]);

assert_eq!(cpu.memory.read(0x0011), 0b0100_0111);
assert_no_flags(&cpu);
}

#[test]
fn test_0x56_lsr_zero_page_x_shifts_right_with_carry_correctly() {
let mut cpu = CPU::new();
cpu.register_x = 0x01;
cpu.memory.write(0x0011, 0b1000_1111);

cpu.load_and_run_without_reset(vec![
0x56, 0x10, 0x00
]);

assert_eq!(cpu.memory.read(0x0011), 0b0100_0111);
assert_flag(&cpu, Flags::Carry);
}

#[test]
fn test_0x56_lsr_zero_page_x_shifts_right_with_zero_correctly() {
let mut cpu = CPU::new();
cpu.register_x = 0x01;
cpu.memory.write(0x0011, 0x00);

cpu.load_and_run_without_reset(vec![
0x56, 0x10, 0x00
]);

assert_eq!(cpu.memory.read(0x0011), 0x00);
assert_flag(&cpu, Flags::Zero);
}

#[test]
fn test_0x4e_lsr_absolute_shifts_right_without_carry_correctly() {
let mut cpu = CPU::new();
cpu.memory.write(0x1011, 0b0100_0110);

cpu.load_and_run_without_reset(vec![
0x4E, 0x11, 0x10, 0x00
]);

assert_eq!(cpu.memory.read(0x1011), 0b0010_0011);
assert_no_flags(&cpu);
}

#[test]
fn test_0x4e_lsr_absolute_shifts_right_with_carry_correctly() {
let mut cpu = CPU::new();
cpu.memory.write(0x1011, 0b0011_1111);

cpu.load_and_run_without_reset(vec![
0x4E, 0x11, 0x10, 0x00
]);

assert_eq!(cpu.memory.read(0x1011), 0b0001_1111);
assert_flag(&cpu, Flags::Carry);
}

#[test]
fn test_0x4e_lsr_absolute_shifts_right_with_zero_correctly() {
let mut cpu = CPU::new();
cpu.memory.write(0x1011, 0x00);

cpu.load_and_run_without_reset(vec![
0x4E, 0x11, 0x10, 0x00
]);

assert_eq!(cpu.memory.read(0x1011), 0x00);
assert_flag(&cpu, Flags::Zero);
}

#[test]
fn test_0x5e_lsr_absolute_x_shifts_right_without_carry_correctly() {
let mut cpu = CPU::new();
cpu.register_x = 0x01;
cpu.memory.write(0x1012, 0b1010_1010);

cpu.load_and_run_without_reset(vec![
0x5E, 0x11, 0x10, 0x00
]);

assert_eq!(cpu.memory.read(0x1012), 0b0101_0101);
assert_no_flags(&cpu);
}

#[test]
fn test_0x5e_lsr_absolute_x_shifts_right_with_carry_correctly() {
let mut cpu = CPU::new();
cpu.register_x = 0x01;
cpu.memory.write(0x1012, 0b1010_1011);

cpu.load_and_run_without_reset(vec![
0x5E, 0x11, 0x10, 0x00
]);

assert_eq!(cpu.memory.read(0x1012), 0b0101_0101);
assert_flag(&cpu, Flags::Carry);
}

#[test]
fn test_0x5e_lsr_absolute_x_shifts_right_with_zero_correctly() {
let mut cpu = CPU::new();
cpu.register_x = 0x01;
cpu.memory.write(0x1012, 0x00);

cpu.load_and_run_without_reset(vec![
0x5E, 0x11, 0x10, 0x00
]);

assert_eq!(cpu.memory.read(0x1012), 0x00);
assert_flag(&cpu, Flags::Zero);
}

0 comments on commit c36761e

Please sign in to comment.