mirror of
https://github.com/mre/mos6502.git
synced 2024-12-01 11:51:51 +00:00
Merge pull request #21 from typelist/master
Implement LSR, INC, INX, INY
This commit is contained in:
commit
40fe0a2ad4
114
src/machine.rs
114
src/machine.rs
@ -138,6 +138,22 @@ impl Machine {
|
|||||||
self.dec_x();
|
self.dec_x();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(instruction::INC, instruction::UseAddress(addr)) => {
|
||||||
|
let m = self.memory.get_byte(addr);
|
||||||
|
let m = m + 1;
|
||||||
|
self.memory.set_byte(addr, m);
|
||||||
|
let i = m as i8;
|
||||||
|
Machine::set_flags_from_i8(&mut self.registers.status, i);
|
||||||
|
}
|
||||||
|
(instruction::INX, instruction::UseImplied) => {
|
||||||
|
let x = self.registers.index_x + 1;
|
||||||
|
self.load_x_register(x);
|
||||||
|
}
|
||||||
|
(instruction::INY, instruction::UseImplied) => {
|
||||||
|
let y = self.registers.index_y + 1;
|
||||||
|
self.load_y_register(y);
|
||||||
|
}
|
||||||
|
|
||||||
(instruction::JMP, instruction::UseAddress(addr)) => {
|
(instruction::JMP, instruction::UseAddress(addr)) => {
|
||||||
self.jump(addr)
|
self.jump(addr)
|
||||||
}
|
}
|
||||||
@ -172,6 +188,19 @@ impl Machine {
|
|||||||
self.load_y_register(val as i8);
|
self.load_y_register(val as i8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(instruction::LSR, instruction::UseImplied) => {
|
||||||
|
// Accumulator mode
|
||||||
|
let mut val = self.registers.accumulator as u8;
|
||||||
|
Machine::shift_right_with_flags(&mut val,
|
||||||
|
&mut self.registers.status);
|
||||||
|
self.registers.accumulator = val as i8;
|
||||||
|
}
|
||||||
|
(instruction::LSR, instruction::UseAddress(addr)) => {
|
||||||
|
Machine::shift_right_with_flags(
|
||||||
|
self.memory.get_byte_mut_ref(addr),
|
||||||
|
&mut self.registers.status);
|
||||||
|
}
|
||||||
|
|
||||||
(instruction::SBC, instruction::UseImmediate(val)) => {
|
(instruction::SBC, instruction::UseImmediate(val)) => {
|
||||||
debug!("subtract with carry immediate: {}", val);
|
debug!("subtract with carry immediate: {}", val);
|
||||||
self.subtract_with_carry(val as i8);
|
self.subtract_with_carry(val as i8);
|
||||||
@ -252,11 +281,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_register_with_flags(register: &mut i8,
|
fn set_flags_from_i8(status: &mut Status, value: i8) {
|
||||||
status: &mut Status,
|
|
||||||
value: i8) {
|
|
||||||
*register = value;
|
|
||||||
|
|
||||||
let is_zero = value == 0;
|
let is_zero = value == 0;
|
||||||
let is_negative = value < 0;
|
let is_negative = value < 0;
|
||||||
|
|
||||||
@ -267,22 +292,37 @@ impl Machine {
|
|||||||
..StatusArgs::none() } ));
|
..StatusArgs::none() } ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn shift_right_with_flags(p_val: &mut u8, status: &mut Status) {
|
||||||
|
let bit0 = *p_val & 1;
|
||||||
|
*p_val = *p_val >> 1;
|
||||||
|
status.set_with_mask(
|
||||||
|
PS_CARRY,
|
||||||
|
Status::new(StatusArgs { carry: bit0 == 1,
|
||||||
|
..StatusArgs::none() } ));
|
||||||
|
Machine::set_flags_from_i8(status, *p_val as i8);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_i8_with_flags(mem: &mut i8, status: &mut Status, value: i8) {
|
||||||
|
*mem = value;
|
||||||
|
Machine::set_flags_from_i8(status, value);
|
||||||
|
}
|
||||||
|
|
||||||
fn load_x_register(&mut self, value: i8) {
|
fn load_x_register(&mut self, value: i8) {
|
||||||
Machine::load_register_with_flags(&mut self.registers.index_x,
|
Machine::set_i8_with_flags(&mut self.registers.index_x,
|
||||||
&mut self.registers.status,
|
&mut self.registers.status,
|
||||||
value);
|
value);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_y_register(&mut self, value: i8) {
|
fn load_y_register(&mut self, value: i8) {
|
||||||
Machine::load_register_with_flags(&mut self.registers.index_y,
|
Machine::set_i8_with_flags(&mut self.registers.index_y,
|
||||||
&mut self.registers.status,
|
&mut self.registers.status,
|
||||||
value);
|
value);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_accumulator(&mut self, value: i8) {
|
fn load_accumulator(&mut self, value: i8) {
|
||||||
Machine::load_register_with_flags(&mut self.registers.accumulator,
|
Machine::set_i8_with_flags(&mut self.registers.accumulator,
|
||||||
&mut self.registers.status,
|
&mut self.registers.status,
|
||||||
value);
|
value);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_with_carry(&mut self, value: i8) {
|
fn add_with_carry(&mut self, value: i8) {
|
||||||
@ -563,6 +603,52 @@ fn decrement_memory_test() {
|
|||||||
assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true);
|
assert_eq!(machine.registers.status.contains(PS_NEGATIVE), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn logical_shift_right_test() {
|
||||||
|
// Testing UseImplied version (which targets the accumulator) only, for now
|
||||||
|
|
||||||
|
let mut machine = Machine::new();
|
||||||
|
machine.execute_instruction((instruction::LDA,
|
||||||
|
instruction::UseImmediate(0)));
|
||||||
|
machine.execute_instruction((instruction::LSR,
|
||||||
|
instruction::UseImplied));
|
||||||
|
assert_eq!(machine.registers.accumulator, 0);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_CARRY), false);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_ZERO), true);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);
|
||||||
|
|
||||||
|
machine.execute_instruction((instruction::LDA,
|
||||||
|
instruction::UseImmediate(1)));
|
||||||
|
machine.execute_instruction((instruction::LSR,
|
||||||
|
instruction::UseImplied));
|
||||||
|
assert_eq!(machine.registers.accumulator, 0);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_CARRY), true);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_ZERO), true);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);
|
||||||
|
|
||||||
|
machine.execute_instruction((instruction::LDA,
|
||||||
|
instruction::UseImmediate(255)));
|
||||||
|
machine.execute_instruction((instruction::LSR,
|
||||||
|
instruction::UseImplied));
|
||||||
|
assert_eq!(machine.registers.accumulator, 0x7F);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_CARRY), true);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_ZERO), false);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);
|
||||||
|
|
||||||
|
machine.execute_instruction((instruction::LDA,
|
||||||
|
instruction::UseImmediate(254)));
|
||||||
|
machine.execute_instruction((instruction::LSR,
|
||||||
|
instruction::UseImplied));
|
||||||
|
assert_eq!(machine.registers.accumulator, 0x7F);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_CARRY), false);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_ZERO), false);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_NEGATIVE), false);
|
||||||
|
assert_eq!(machine.registers.status.contains(PS_OVERFLOW), false);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn dec_x_test() {
|
fn dec_x_test() {
|
||||||
let mut machine = Machine::new();
|
let mut machine = Machine::new();
|
||||||
|
@ -61,6 +61,10 @@ impl Memory {
|
|||||||
self.bytes[address.to_uint()]
|
self.bytes[address.to_uint()]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_byte_mut_ref(&mut self, address: Address) -> &mut u8 {
|
||||||
|
&mut self.bytes[address.to_uint()]
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_slice(&self, Address(start): Address,
|
pub fn get_slice(&self, Address(start): Address,
|
||||||
AddressDiff(diff): AddressDiff) -> &[u8] {
|
AddressDiff(diff): AddressDiff) -> &[u8] {
|
||||||
let start = start as uint;
|
let start = start as uint;
|
||||||
|
Loading…
Reference in New Issue
Block a user