LSR instruction

This commit is contained in:
2022-11-27 09:08:44 -05:00
parent 9980ce2c9f
commit 253201c6c5
3 changed files with 68 additions and 0 deletions
+54
View File
@@ -299,6 +299,26 @@ impl CPU {
self.increment_cycles_shift(addressing_mode);
}
fn lsr(&mut self, bus: &mut Bus, addressing_mode: AddressingMode) {
let target = match addressing_mode {
AddressingMode::Accumulator => self.registers.a,
_ => match self.registers.is_16bit_mode() {
true => self.get_16bit_from_address(bus, addressing_mode),
false => self.get_8bit_from_address(bus, addressing_mode) as u16,
}
};
if self.registers.is_16bit_mode() {
let (result, affected_flags) = alu::lsr(target);
self.set_16bit_to_address(bus, addressing_mode, result);
self.registers.set_flags(&affected_flags);
} else {
let (result, affected_flags) = alu::lsr(target as u8);
self.set_8bit_to_address(bus, addressing_mode, result);
self.registers.set_flags(&affected_flags);
}
self.increment_cycles_shift(addressing_mode);
}
fn do_bit<T: SnesNum>(&mut self, accumulator: T, value: T, addressing_mode: AddressingMode) {
let (result, _) = alu::and(accumulator, value);
// Immediate addressing affects only the zero flag
@@ -597,6 +617,12 @@ impl CPU {
0xE8 => self.inx(),
// INY
0xC8 => self.iny(),
// LSR
0x4A => self.lsr(bus, A::Accumulator),
0x4E => self.lsr(bus, A::Absolute),
0x46 => self.lsr(bus, A::DirectPage),
0x5E => self.lsr(bus, A::AbsoluteIndexed(I::X)),
0x56 => self.lsr(bus, A::DirectPageIndexed(I::X)),
_ => println!("Invalid opcode: {:02X}", opcode),
}
}
@@ -691,6 +717,25 @@ mod cpu_instructions_tests {
assert!(cpu.registers.get_negative_flag());
}
#[test]
fn test_lsr() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.a = 0b00000000_00000011;
cpu.registers.pbr = 0x00;
cpu.registers.pc = 0x0000;
cpu.registers.set_memory_select_flag(false);
cpu.registers.set_negative_flag(true);
cpu.registers.set_carry_flag(false);
cpu.lsr(&mut bus, AddressingMode::Accumulator);
assert_eq!(cpu.registers.a, 0b00000000_00000001);
assert_eq!(cpu.registers.pc, 0x01);
assert_eq!(cpu.cycles, 4);
assert!(cpu.registers.get_carry_flag());
assert!(!cpu.registers.get_zero_flag());
assert!(!cpu.registers.get_negative_flag());
}
#[test]
fn test_bit() {
let mut cpu = CPU::new();
@@ -1262,4 +1307,13 @@ mod cpu_instructions_tests {
assert!(!cpu.registers.get_negative_flag());
assert!(!cpu.registers.get_zero_flag());
}
#[test]
fn test_nop() {
let mut cpu = CPU::new();
cpu.registers.pc = 0x0000;
cpu.nop();
assert_eq!(cpu.registers.pc, 0x01);
assert_eq!(cpu.cycles, 2);
}
}
+9
View File
@@ -109,6 +109,15 @@ pub fn asl<T: SnesNum>(target: T) -> (T, [Flags; 3]) {
])
}
pub fn lsr<T: SnesNum>(target: T) -> (T, [Flags; 3]) {
let result = target.lsr();
(result, [
Negative(false),
Zero(result.is_zero()),
Carry(result.to_u32() & 1 == 1), // High bit becomes carry
])
}
pub fn eor<T: SnesNum>(target: T, value: T) -> (T, [Flags; 2]) {
let result = target.xor(value);
(result, [
+5
View File
@@ -6,6 +6,7 @@ pub trait SnesNum: Copy + Clone + Sized + Eq + PartialEq {
fn sbc_snes(&self, v: Self, carry: bool) -> Self;
fn and(&self, v: Self) -> Self;
fn asl(&self) -> Self;
fn lsr(&self) -> Self;
fn xor(&self, v: Self) -> Self;
fn is_negative(&self) -> bool;
fn is_zero(&self) -> bool;
@@ -68,6 +69,10 @@ macro_rules! define_impl {
(* self) << 1
}
fn lsr(&self) -> $t {
(* self) >> 1
}
fn xor(&self, v: $t) -> $t {
(* self) ^ v
}