ORA instruction

This commit is contained in:
2022-11-27 09:28:05 -05:00
parent 31aa639a3c
commit 41111c3158
3 changed files with 101 additions and 1 deletions
+49
View File
@@ -263,6 +263,22 @@ impl CPU {
self.increment_cycles_bitwise(addressing_mode);
}
fn ora(&mut self, bus: &Bus, addressing_mode: AddressingMode) {
let target = self.registers.a;
if self.registers.is_16bit_mode() {
let value = self.get_16bit_from_address(bus, addressing_mode);
let (result, affected_flags) = alu::ora(target, value);
self.registers.a = result;
self.registers.set_flags(&affected_flags);
} else {
let value = self.get_8bit_from_address(bus, addressing_mode);
let (result, affected_flags) = alu::ora(target as u8, value);
self.registers.set_low_a(result);
self.registers.set_flags(&affected_flags);
}
self.increment_cycles_bitwise(addressing_mode);
}
fn eor(&mut self, bus: &Bus, addressing_mode: AddressingMode) {
let target = self.registers.a;
if self.registers.is_16bit_mode() {
@@ -629,6 +645,22 @@ impl CPU {
0x56 => self.lsr(bus, A::DirectPageIndexed(I::X)),
// NOP
0xEA => self.nop(),
// ORA
0x09 => self.ora(bus, A::Immediate),
0x0D => self.ora(bus, A::Absolute),
0x0F => self.ora(bus, A::AbsoluteLong),
0x05 => self.ora(bus, A::DirectPage),
0x12 => self.ora(bus, A::DirectPageIndirect),
0x07 => self.ora(bus, A::DirectPageIndirectLong),
0x1D => self.ora(bus, A::AbsoluteIndexed(I::X)),
0x1F => self.ora(bus, A::AbsoluteLongIndexed(I::X)),
0x19 => self.ora(bus, A::AbsoluteIndexed(I::Y)),
0x15 => self.ora(bus, A::DirectPageIndexed(I::X)),
0x01 => self.ora(bus, A::DirectPageIndexedIndirect(I::X)),
0x11 => self.ora(bus, A::DirectPageIndirectIndexed(I::Y)),
0x17 => self.ora(bus, A::DirectPageIndirectLongIndexed(I::Y)),
0x03 => self.ora(bus, A::StackRelative),
0x13 => self.ora(bus, A::StackRelativeIndirectIndexed(I::Y)),
_ => println!("Invalid opcode: {:02X}", opcode),
}
}
@@ -706,6 +738,23 @@ mod cpu_instructions_tests {
assert!(!cpu.registers.get_zero_flag());
}
#[test]
fn test_ora() {
let mut cpu = CPU::new();
let mut bus = Bus::new();
cpu.registers.a = 0x0F;
cpu.registers.pbr = 0x00;
cpu.registers.pc = 0x0000;
cpu.registers.set_memory_select_flag(true);
bus.write(0x000001, 0xF0);
cpu.ora(&bus, AddressingMode::Immediate);
assert_eq!(cpu.registers.a, 0xFF);
assert_eq!(cpu.registers.pc, 0x02);
assert_eq!(cpu.cycles, 2);
assert!(!cpu.registers.get_zero_flag());
assert!(cpu.registers.get_negative_flag());
}
#[test]
fn test_asl() {
let mut cpu = CPU::new();
+47 -1
View File
@@ -114,7 +114,7 @@ pub fn lsr<T: SnesNum>(target: T) -> (T, [Flags; 3]) {
(result, [
Negative(false),
Zero(result.is_zero()),
Carry(result.to_u32() & 1 == 1), // High bit becomes carry
Carry(target.to_u32() & 1 == 1), // Low bit becomes carry
])
}
@@ -126,6 +126,14 @@ pub fn eor<T: SnesNum>(target: T, value: T) -> (T, [Flags; 2]) {
])
}
pub fn ora<T: SnesNum>(target: T, value: T) -> (T, [Flags; 2]) {
let result = target.ora(value);
(result, [
Negative(result.is_negative()),
Zero(result.is_zero()),
])
}
#[cfg(test)]
mod alu_tests {
@@ -334,6 +342,23 @@ mod alu_tests {
assert_eq!(affected_flags, [Negative(false), Zero(true), Carry(true)]);
}
#[test]
fn test_lsr() {
// 8 bit
let (result, affected_flags) = lsr(0b0101_0101_u8);
assert_eq!(result, 0b0010_1010);
assert_eq!(affected_flags, [Negative(false), Zero(false), Carry(true)]);
let (result, affected_flags) = lsr(0x01_u8);
assert_eq!(result, 0);
assert_eq!(affected_flags, [Negative(false), Zero(true), Carry(true)]);
// 16 bit
let (result, affected_flags) = lsr(0b10000000_00000000_u16);
assert_eq!(result, 0b01000000_00000000);
assert_eq!(affected_flags, [Negative(false), Zero(false), Carry(false)]);
}
#[test]
fn test_xor() {
// 8 bit
@@ -354,4 +379,25 @@ mod alu_tests {
assert_eq!(result, 0b10000000_00000000);
assert_eq!(affected_flags, [Negative(true), Zero(false)]);
}
#[test]
fn test_ora() {
// 8 bit
let (result, affected_flags) = ora(0b0101_0101_u8, 0b1010_1010_u8);
assert_eq!(result, 0xFF);
assert_eq!(affected_flags, [Negative(true), Zero(false)]);
let (result, affected_flags) = ora(0b1000_0000_u8, 0b0000_0000_u8);
assert_eq!(result, 0b1000_0000);
assert_eq!(affected_flags, [Negative(true), Zero(false)]);
// 16 bit
let (result, affected_flags) = ora(0b01010101_00000000_u16, 0b01010101_00000000_u16);
assert_eq!(result, 0b01010101_00000000_u16);
assert_eq!(affected_flags, [Negative(false), Zero(false)]);
let (result, affected_flags) = ora(0b00000000_00000000_u16, 0b00000000_00000000_u16);
assert_eq!(result, 0);
assert_eq!(affected_flags, [Negative(false), Zero(true)]);
}
}
+5
View File
@@ -8,6 +8,7 @@ pub trait SnesNum: Copy + Clone + Sized + Eq + PartialEq {
fn asl(&self) -> Self;
fn lsr(&self) -> Self;
fn xor(&self, v: Self) -> Self;
fn ora(&self, v: Self) -> Self;
fn is_negative(&self) -> bool;
fn is_zero(&self) -> bool;
fn next_to_highest_bit(&self) -> bool;
@@ -77,6 +78,10 @@ macro_rules! define_impl {
(* self) ^ v
}
fn ora(&self, v: $t) -> $t {
(* self) | v
}
fn is_negative(&self) -> bool {
(*self) & !(<$t>::MAX >> 1) != 0
}