mirror of
https://github.com/FranLMSP/snes.git
synced 2026-08-03 08:30:01 -04:00
ROL and ROR instructions
This commit is contained in:
@@ -340,6 +340,10 @@ impl CPU {
|
||||
self.cycles += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn increment_cycles_rep(&mut self) {
|
||||
self.registers.increment_pc(2); self.cycles += 3;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -743,6 +743,46 @@ impl CPU {
|
||||
self.increment_cycles_rep();
|
||||
}
|
||||
|
||||
fn rol(&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::rol(target, self.registers.get_carry_flag());
|
||||
self.set_16bit_to_address(bus, addressing_mode, result);
|
||||
self.registers.set_flags(&affected_flags);
|
||||
} else {
|
||||
let (result, affected_flags) = alu::rol(target as u8, self.registers.get_carry_flag());
|
||||
self.set_8bit_to_address(bus, addressing_mode, result);
|
||||
self.registers.set_flags(&affected_flags);
|
||||
}
|
||||
self.increment_cycles_shift(addressing_mode);
|
||||
}
|
||||
|
||||
fn ror(&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::ror(target, self.registers.get_carry_flag());
|
||||
self.set_16bit_to_address(bus, addressing_mode, result);
|
||||
self.registers.set_flags(&affected_flags);
|
||||
} else {
|
||||
let (result, affected_flags) = alu::ror(target as u8, self.registers.get_carry_flag());
|
||||
self.set_8bit_to_address(bus, addressing_mode, result);
|
||||
self.registers.set_flags(&affected_flags);
|
||||
}
|
||||
self.increment_cycles_shift(addressing_mode);
|
||||
}
|
||||
|
||||
pub fn execute_opcode(&mut self, opcode: u8, bus: &mut Bus) {
|
||||
type A = AddressingMode;
|
||||
type I = IndexRegister;
|
||||
@@ -999,6 +1039,18 @@ impl CPU {
|
||||
0x7A => self.ply(bus),
|
||||
// REP
|
||||
0xC2 => self.rep(bus),
|
||||
// ROL
|
||||
0x2A => self.rol(bus, AddressingMode::Accumulator),
|
||||
0x2E => self.rol(bus, AddressingMode::Immediate),
|
||||
0x26 => self.rol(bus, AddressingMode::DirectPage),
|
||||
0x3E => self.rol(bus, AddressingMode::AbsoluteIndexed(I::X)),
|
||||
0x36 => self.rol(bus, AddressingMode::DirectPageIndexed(I::X)),
|
||||
// ROR
|
||||
0x6A => self.ror(bus, AddressingMode::Accumulator),
|
||||
0x6E => self.ror(bus, AddressingMode::Immediate),
|
||||
0x66 => self.ror(bus, AddressingMode::DirectPage),
|
||||
0x7E => self.ror(bus, AddressingMode::AbsoluteIndexed(I::X)),
|
||||
0x76 => self.ror(bus, AddressingMode::DirectPageIndexed(I::X)),
|
||||
_ => println!("Invalid opcode: {:02X}", opcode),
|
||||
}
|
||||
}
|
||||
@@ -2093,4 +2145,35 @@ mod cpu_instructions_tests {
|
||||
assert_eq!(cpu.registers.pc, 0x0002);
|
||||
assert_eq!(cpu.cycles, 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rol() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.set_16bit_mode(false);
|
||||
cpu.registers.a = 0b0100_0000;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.rol(&mut bus, AddressingMode::Accumulator);
|
||||
assert_eq!(cpu.registers.get_negative_flag(), true);
|
||||
assert_eq!(cpu.registers.get_zero_flag(), false);
|
||||
assert_eq!(cpu.registers.a, 0b1000_0000);
|
||||
assert_eq!(cpu.registers.pc, 0x0001);
|
||||
assert_eq!(cpu.cycles, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ror() {
|
||||
let mut cpu = CPU::new();
|
||||
let mut bus = Bus::new();
|
||||
cpu.registers.set_16bit_mode(false);
|
||||
cpu.registers.set_carry_flag(true);
|
||||
cpu.registers.a = 0x00;
|
||||
cpu.registers.pc = 0x0000;
|
||||
cpu.ror(&mut bus, AddressingMode::Accumulator);
|
||||
assert_eq!(cpu.registers.get_carry_flag(), false);
|
||||
assert_eq!(cpu.registers.get_zero_flag(), false);
|
||||
assert_eq!(cpu.registers.a, 0b1000_0000);
|
||||
assert_eq!(cpu.registers.pc, 0x0001);
|
||||
assert_eq!(cpu.cycles, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +134,24 @@ pub fn ora<T: SnesNum>(target: T, value: T) -> (T, [Flags; 2]) {
|
||||
])
|
||||
}
|
||||
|
||||
pub fn rol<T: SnesNum>(target: T, carry: bool) -> (T, [Flags; 3]) {
|
||||
let result = target.rol(carry);
|
||||
(result, [
|
||||
Negative(result.is_negative()),
|
||||
Zero(result.is_zero()),
|
||||
Carry(target.is_negative()),
|
||||
])
|
||||
}
|
||||
|
||||
pub fn ror<T: SnesNum>(target: T, carry: bool) -> (T, [Flags; 3]) {
|
||||
let result = target.ror(carry);
|
||||
(result, [
|
||||
Negative(result.is_negative()),
|
||||
Zero(result.is_zero()),
|
||||
Carry(target.lowest_bit()),
|
||||
])
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod alu_tests {
|
||||
@@ -400,4 +418,26 @@ mod alu_tests {
|
||||
assert_eq!(result, 0);
|
||||
assert_eq!(affected_flags, [Negative(false), Zero(true)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rol() {
|
||||
let (result, affected_flags) = rol(0b1000_0000_u8, false);
|
||||
assert_eq!(result, 0);
|
||||
assert_eq!(affected_flags, [Negative(false), Zero(true), Carry(true)]);
|
||||
|
||||
let (result, affected_flags) = rol(0b0100_0000_u8, true);
|
||||
assert_eq!(result, 0b10000001);
|
||||
assert_eq!(affected_flags, [Negative(true), Zero(false), Carry(false)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ror() {
|
||||
let (result, affected_flags) = ror(0b0000_0001_u8, false);
|
||||
assert_eq!(result, 0);
|
||||
assert_eq!(affected_flags, [Negative(false), Zero(true), Carry(true)]);
|
||||
|
||||
let (result, affected_flags) = ror(0b0000_0000_u8, true);
|
||||
assert_eq!(result, 0b10000000);
|
||||
assert_eq!(affected_flags, [Negative(true), Zero(false), Carry(false)]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user