1
0
mirror of https://github.com/mre/mos6502.git synced 2024-12-22 12:29:31 +00:00

Fix build for latest rustc

This commit is contained in:
Matthias Endler 2017-10-08 17:27:53 +02:00 committed by GitHub
commit 5b57497ea4
9 changed files with 1349 additions and 1105 deletions

View File

@ -3,3 +3,4 @@
Alex Weisberger <alex.m.weisberger@gmail.com>
Andrew Keeton <andrewrkeeton@gmail.com>
Johannes Muenzel <jmuenzel@gmail.com>
Matthias Endler <matthias-endler@gmx.net>

View File

@ -39,5 +39,6 @@ name = "emu6502"
name = "emu6502"
[dependencies]
log = "0.2.3"
bitflags = "0.9.1"
log = "0.3.8"
num = "0.1"

View File

@ -25,16 +25,15 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
use std::num::Int;
use std::ops::Add;
// The idea here is that it doesn't make sense to add two addresses, but it
// does make sense to add an address and an "address-difference". (If this
// is too annoying to work with we should let it go.)
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct AddressDiff(pub i32);
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct Address(pub u16);
impl Add<AddressDiff> for Address {
@ -57,7 +56,7 @@ impl Add for AddressDiff {
}
}
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct CheckedAddressDiff(u16);
impl Add<CheckedAddressDiff> for Address {
@ -77,7 +76,7 @@ impl Add<CheckedAddressDiff> for Address {
impl Address {
pub fn to_u16(&self) -> u16 {
match *self {
Address(address_) => address_
Address(address_) => address_,
}
}
@ -93,4 +92,3 @@ impl Address {
(self.to_u16() & 0x00ff) as u8
}
}

File diff suppressed because it is too large Load Diff

View File

@ -25,20 +25,17 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#![feature(core)]
#![feature(hash)]
#![feature(rustc_private)]
// Needed for debug! / log! macros
#[macro_use]
extern crate log;
extern crate num;
#[macro_use]
extern crate rustc_bitflags;
extern crate bitflags;
pub mod address;
pub mod instruction;
pub mod machine;
pub mod memory;
pub mod range_incl;
pub mod registers;

View File

@ -31,22 +31,21 @@ use address::{Address, AddressDiff};
use instruction;
use instruction::{DecodedInstr, Instruction, OpInput};
use memory::Memory;
use range_incl::range_incl;
use registers::{Registers, StackPointer, Status, StatusArgs};
use registers::{PS_NEGATIVE, PS_DECIMAL_MODE, PS_OVERFLOW, PS_ZERO, PS_CARRY,
PS_DISABLE_INTERRUPTS};
#[derive(Copy)]
#[derive(Clone)]
pub struct Machine {
pub registers: Registers,
pub memory: Memory
pub memory: Memory,
}
impl Machine {
pub fn new() -> Machine {
Machine {
registers: Registers::new(),
memory: Memory::new()
memory: Memory::new(),
}
}
@ -62,19 +61,17 @@ impl Machine {
let extra_bytes = am.extra_bytes();
let num_bytes = AddressDiff(1) + extra_bytes;
let data_start = self.registers.program_counter
+ AddressDiff(1);
let data_start = self.registers.program_counter + AddressDiff(1);
let slice = self.memory.get_slice(data_start, extra_bytes);
let am_out = am.process(self, slice);
// Increment program counter
self.registers.program_counter =
self.registers.program_counter + num_bytes;
self.registers.program_counter = self.registers.program_counter + num_bytes;
Some((instr, am_out))
}
_ => None
_ => None,
}
}
@ -101,32 +98,29 @@ impl Machine {
(Instruction::ASL, OpInput::UseImplied) => {
// Accumulator mode
let mut val = self.registers.accumulator as u8;
Machine::shift_left_with_flags(&mut val,
&mut self.registers.status);
Machine::shift_left_with_flags(&mut val, &mut self.registers.status);
self.registers.accumulator = val as i8;
}
(Instruction::ASL, OpInput::UseAddress(addr)) => {
Machine::shift_left_with_flags(
self.memory.get_byte_mut_ref(addr),
&mut self.registers.status);
&mut self.registers.status,
);
}
(Instruction::BCC, OpInput::UseRelative(rel)) => {
let addr = self.registers.program_counter
+ AddressDiff(rel as i32);
let addr = self.registers.program_counter + AddressDiff(rel as i32);
self.branch_if_carry_clear(addr);
}
(Instruction::BCS, OpInput::UseRelative(rel)) => {
let addr = self.registers.program_counter
+ AddressDiff(rel as i32);
let addr = self.registers.program_counter + AddressDiff(rel as i32);
self.branch_if_carry_set(addr);
}
(Instruction::BEQ, OpInput::UseRelative(rel)) => {
let addr = self.registers.program_counter
+ AddressDiff(rel as i32);
let addr = self.registers.program_counter + AddressDiff(rel as i32);
self.branch_if_equal(addr);
}
@ -146,34 +140,33 @@ impl Machine {
self.registers.status.set_with_mask(
PS_ZERO | PS_NEGATIVE | PS_OVERFLOW,
Status::new(StatusArgs { zero: is_zero,
Status::new(StatusArgs {
zero: is_zero,
negative: bit7,
overflow: bit6,
..StatusArgs::none() } ));
..StatusArgs::none()
}),
);
}
(Instruction::BMI, OpInput::UseRelative(rel)) => {
let addr = self.registers.program_counter
+ AddressDiff(rel as i32);
let addr = self.registers.program_counter + AddressDiff(rel as i32);
debug!("branch if minus relative. address: {:?}", addr);
self.branch_if_minus(addr);
}
(Instruction::BPL, OpInput::UseRelative(rel)) => {
let addr = self.registers.program_counter
+ AddressDiff(rel as i32);
let addr = self.registers.program_counter + AddressDiff(rel as i32);
self.branch_if_positive(addr);
}
(Instruction::BVC, OpInput::UseRelative(rel)) => {
let addr = self.registers.program_counter
+ AddressDiff(rel as i32);
let addr = self.registers.program_counter + AddressDiff(rel as i32);
self.branch_if_overflow_clear(addr);
}
(Instruction::BVS, OpInput::UseRelative(rel)) => {
let addr = self.registers.program_counter
+ AddressDiff(rel as i32);
let addr = self.registers.program_counter + AddressDiff(rel as i32);
self.branch_if_overflow_set(addr);
}
@ -214,9 +207,7 @@ impl Machine {
self.compare_with_y_register(val);
}
(Instruction::DEC, OpInput::UseAddress(addr)) => {
self.decrement_memory(addr)
}
(Instruction::DEC, OpInput::UseAddress(addr)) => self.decrement_memory(addr),
(Instruction::DEX, OpInput::UseImplied) => {
self.dec_x();
@ -246,9 +237,7 @@ impl Machine {
self.load_y_register(y);
}
(Instruction::JMP, OpInput::UseAddress(addr)) => {
self.jump(addr)
}
(Instruction::JMP, OpInput::UseAddress(addr)) => self.jump(addr),
(Instruction::LDA, OpInput::UseImmediate(val)) => {
debug!("load A immediate: {}", val);
@ -283,14 +272,14 @@ impl Machine {
(Instruction::LSR, OpInput::UseImplied) => {
// Accumulator mode
let mut val = self.registers.accumulator as u8;
Machine::shift_right_with_flags(&mut val,
&mut self.registers.status);
Machine::shift_right_with_flags(&mut val, &mut self.registers.status);
self.registers.accumulator = val as i8;
}
(Instruction::LSR, OpInput::UseAddress(addr)) => {
Machine::shift_right_with_flags(
self.memory.get_byte_mut_ref(addr),
&mut self.registers.status);
&mut self.registers.status,
);
}
(Instruction::ORA, OpInput::UseImmediate(val)) => {
@ -328,26 +317,26 @@ impl Machine {
(Instruction::ROL, OpInput::UseImplied) => {
// Accumulator mode
let mut val = self.registers.accumulator as u8;
Machine::rotate_left_with_flags(&mut val,
&mut self.registers.status);
Machine::rotate_left_with_flags(&mut val, &mut self.registers.status);
self.registers.accumulator = val as i8;
}
(Instruction::ROL, OpInput::UseAddress(addr)) => {
Machine::rotate_left_with_flags(
self.memory.get_byte_mut_ref(addr),
&mut self.registers.status);
&mut self.registers.status,
);
}
(Instruction::ROR, OpInput::UseImplied) => {
// Accumulator mode
let mut val = self.registers.accumulator as u8;
Machine::rotate_right_with_flags(&mut val,
&mut self.registers.status);
Machine::rotate_right_with_flags(&mut val, &mut self.registers.status);
self.registers.accumulator = val as i8;
}
(Instruction::ROR, OpInput::UseAddress(addr)) => {
Machine::rotate_right_with_flags(
self.memory.get_byte_mut_ref(addr),
&mut self.registers.status);
&mut self.registers.status,
);
}
(Instruction::SBC, OpInput::UseImmediate(val)) => {
@ -356,8 +345,7 @@ impl Machine {
}
(Instruction::SBC, OpInput::UseAddress(addr)) => {
let val = self.memory.get_byte(addr) as i8;
debug!("subtract with carry. address: {:?}. value: {}",
addr, val);
debug!("subtract with carry. address: {:?}. value: {}", addr, val);
self.subtract_with_carry(val);
}
@ -414,8 +402,10 @@ impl Machine {
debug!("NOP instruction");
}
(_, _) => {
debug!("attempting to execute unimplemented or invalid \
instruction");
debug!(
"attempting to execute unimplemented or invalid \
instruction"
);
}
};
}
@ -425,7 +415,7 @@ impl Machine {
if let Some(decoded_instr) = self.fetch_next_and_decode() {
self.execute_instruction(decoded_instr);
} else {
break
break;
}
}
}
@ -436,9 +426,12 @@ impl Machine {
status.set_with_mask(
PS_ZERO | PS_NEGATIVE,
Status::new(StatusArgs { zero: is_zero,
Status::new(StatusArgs {
zero: is_zero,
negative: is_negative,
..StatusArgs::none() } ));
..StatusArgs::none()
}),
);
}
fn shift_left_with_flags(p_val: &mut u8, status: &mut Status) {
@ -448,8 +441,11 @@ impl Machine {
*p_val = shifted;
status.set_with_mask(
PS_CARRY,
Status::new(StatusArgs { carry: is_bit_7_set,
..StatusArgs::none() } ));
Status::new(StatusArgs {
carry: is_bit_7_set,
..StatusArgs::none()
}),
);
Machine::set_flags_from_i8(status, *p_val as i8);
}
@ -459,8 +455,11 @@ impl Machine {
*p_val = *p_val >> 1;
status.set_with_mask(
PS_CARRY,
Status::new(StatusArgs { carry: is_bit_0_set,
..StatusArgs::none() } ));
Status::new(StatusArgs {
carry: is_bit_0_set,
..StatusArgs::none()
}),
);
Machine::set_flags_from_i8(status, *p_val as i8);
}
@ -472,8 +471,11 @@ impl Machine {
*p_val = shifted + if is_carry_set { 1 } else { 0 };
status.set_with_mask(
PS_CARRY,
Status::new(StatusArgs { carry: is_bit_7_set,
..StatusArgs::none() } ));
Status::new(StatusArgs {
carry: is_bit_7_set,
..StatusArgs::none()
}),
);
Machine::set_flags_from_i8(status, *p_val as i8);
}
@ -485,8 +487,11 @@ impl Machine {
*p_val = shifted + if is_carry_set { 1 << 7 } else { 0 };
status.set_with_mask(
PS_CARRY,
Status::new(StatusArgs { carry: is_bit_0_set,
..StatusArgs::none() } ));
Status::new(StatusArgs {
carry: is_bit_0_set,
..StatusArgs::none()
}),
);
Machine::set_flags_from_i8(status, *p_val as i8);
}
@ -496,21 +501,27 @@ impl Machine {
}
fn load_x_register(&mut self, value: i8) {
Machine::set_i8_with_flags(&mut self.registers.index_x,
Machine::set_i8_with_flags(
&mut self.registers.index_x,
&mut self.registers.status,
value);
value,
);
}
fn load_y_register(&mut self, value: i8) {
Machine::set_i8_with_flags(&mut self.registers.index_y,
Machine::set_i8_with_flags(
&mut self.registers.index_y,
&mut self.registers.status,
value);
value,
);
}
fn load_accumulator(&mut self, value: i8) {
Machine::set_i8_with_flags(&mut self.registers.accumulator,
Machine::set_i8_with_flags(
&mut self.registers.accumulator,
&mut self.registers.status,
value);
value,
);
}
fn add_with_carry(&mut self, value: i8) {
@ -519,25 +530,33 @@ impl Machine {
debug!("binary-coded decimal not implemented for add_with_carry");
} else {
let a_before: i8 = self.registers.accumulator;
let c_before: i8 = if self.registers.status.contains(PS_CARRY)
{ 1 } else { 0 };
let a_after: i8 = a_before + c_before + value;
let c_before: i8 = if self.registers.status.contains(PS_CARRY) {
1
} else {
0
};
let a_after: i8 = a_before.wrapping_add(c_before).wrapping_add(value);
debug_assert_eq!(a_after as u8, a_before as u8 + c_before as u8
+ value as u8);
debug_assert_eq!(
a_after as u8,
a_before.wrapping_add(c_before).wrapping_add(value) as u8
);
let did_carry = (a_after as u8) < (a_before as u8);
let did_overflow =
(a_before < 0 && value < 0 && a_after >= 0)
|| (a_before > 0 && value > 0 && a_after <= 0);
let did_overflow = (a_before < 0 && value < 0 && a_after >= 0) ||
(a_before > 0 && value > 0 && a_after <= 0);
let mask = PS_CARRY | PS_OVERFLOW;
self.registers.status.set_with_mask(mask,
Status::new(StatusArgs { carry: did_carry,
self.registers.status.set_with_mask(
mask,
Status::new(StatusArgs {
carry: did_carry,
overflow: did_overflow,
..StatusArgs::none() } ));
..StatusArgs::none()
}),
);
self.load_accumulator(a_after);
@ -553,18 +572,23 @@ impl Machine {
// TODO: Implement binary-coded decimal
fn subtract_with_carry(&mut self, value: i8) {
if self.registers.status.contains(PS_DECIMAL_MODE) {
debug!("binary-coded decimal not implemented for \
subtract_with_carry");
debug!(
"binary-coded decimal not implemented for \
subtract_with_carry"
);
} else {
// A - M - (1 - C)
// nc -- 'not carry'
let nc: i8 = if self.registers.status.contains(PS_CARRY)
{ 0 } else { 1 };
let nc: i8 = if self.registers.status.contains(PS_CARRY) {
0
} else {
1
};
let a_before: i8 = self.registers.accumulator;
let a_after = a_before - value - nc;
let a_after = a_before.wrapping_sub(value).wrapping_sub(nc);
// The carry flag is set on unsigned overflow.
let did_carry = (a_after as u8) > (a_before as u8);
@ -575,28 +599,30 @@ impl Machine {
// range of - M - (1 - C) is -128 to 128
// -(127 + 1) to -(-128 + 0)
//
let over = ((nc == 0 && value < 0) || (nc == 1 && value < -1))
&& a_before >= 0
&& a_after < 0;
let over = ((nc == 0 && value < 0) || (nc == 1 && value < -1)) && a_before >= 0 &&
a_after < 0;
let under = (a_before < 0) && (-value - nc < 0)
&& a_after >= 0;
let under = (a_before < 0) && (-value - nc < 0) && a_after >= 0;
let did_overflow = over || under;
let mask = PS_CARRY | PS_OVERFLOW;
self.registers.status.set_with_mask(mask,
Status::new(StatusArgs { carry: did_carry,
self.registers.status.set_with_mask(
mask,
Status::new(StatusArgs {
carry: did_carry,
overflow: did_overflow,
..StatusArgs::none() } ));
..StatusArgs::none()
}),
);
self.load_accumulator(a_after);
}
}
fn decrement_memory(&mut self, addr: Address) {
let value_new = self.memory.get_byte(addr) - 1;
let value_new = self.memory.get_byte(addr).wrapping_sub(1);
self.memory.set_byte(addr, value_new);
@ -605,9 +631,12 @@ impl Machine {
self.registers.status.set_with_mask(
PS_NEGATIVE | PS_ZERO,
Status::new(StatusArgs { negative: is_negative,
Status::new(StatusArgs {
negative: is_negative,
zero: is_zero,
..StatusArgs::none() } ));
..StatusArgs::none()
}),
);
}
fn dec_x(&mut self) {
@ -667,7 +696,7 @@ impl Machine {
// If the C flag is 0, then A (unsigned) < NUM (unsigned) and BCC will branch
// If the C flag is 1, then A (unsigned) >= NUM (unsigned) and BCS will branch
// ...
// The N flag contains most significant bit of the of the subtraction result.
// The N flag contains most significant bit of the subtraction result.
fn compare(&mut self, r: i8, val: u8) {
if r as u8 >= val as u8 {
self.registers.status.insert(PS_CARRY);
@ -681,7 +710,7 @@ impl Machine {
self.registers.status.remove(PS_ZERO);
}
let diff: i8 = (r as i8) - (val as i8);
let diff: i8 = r.wrapping_sub(val as i8);
if diff < 0 {
self.registers.status.insert(PS_NEGATIVE);
} else {
@ -732,11 +761,20 @@ impl Machine {
impl std::fmt::Debug for Machine {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "Machine Dump:\n\nAccumulator: {}",
self.registers.accumulator)
write!(
f,
"Machine Dump:\n\nAccumulator: {}",
self.registers.accumulator
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use num::range_inclusive;
#[test]
fn add_with_carry_test() {
let mut machine = Machine::new();
@ -934,40 +972,32 @@ 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,
OpInput::UseImmediate(0)));
machine.execute_instruction((Instruction::LSR,
OpInput::UseImplied));
machine.execute_instruction((Instruction::LDA, OpInput::UseImmediate(0)));
machine.execute_instruction((Instruction::LSR, OpInput::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,
OpInput::UseImmediate(1)));
machine.execute_instruction((Instruction::LSR,
OpInput::UseImplied));
machine.execute_instruction((Instruction::LDA, OpInput::UseImmediate(1)));
machine.execute_instruction((Instruction::LSR, OpInput::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,
OpInput::UseImmediate(255)));
machine.execute_instruction((Instruction::LSR,
OpInput::UseImplied));
machine.execute_instruction((Instruction::LDA, OpInput::UseImmediate(255)));
machine.execute_instruction((Instruction::LSR, OpInput::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,
OpInput::UseImmediate(254)));
machine.execute_instruction((Instruction::LSR,
OpInput::UseImplied));
machine.execute_instruction((Instruction::LDA, OpInput::UseImmediate(254)));
machine.execute_instruction((Instruction::LSR, OpInput::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);
@ -1129,16 +1159,13 @@ fn branch_if_overflow_set_test() {
}
#[cfg(test)]
fn compare_test_helper<F> (
compare: &mut F,
load_instruction: Instruction
) where F: FnMut(&mut Machine, u8)
fn compare_test_helper<F>(compare: &mut F, load_instruction: Instruction)
where
F: FnMut(&mut Machine, u8),
{
let mut machine = Machine::new();
machine.execute_instruction(
(load_instruction, OpInput::UseImmediate(127))
);
machine.execute_instruction((load_instruction, OpInput::UseImmediate(127)));
compare(&mut machine, 127);
assert!(machine.registers.status.contains(PS_ZERO));
@ -1146,9 +1173,7 @@ fn compare_test_helper<F> (
assert!(!machine.registers.status.contains(PS_NEGATIVE));
machine.execute_instruction(
(load_instruction, OpInput::UseImmediate(127))
);
machine.execute_instruction((load_instruction, OpInput::UseImmediate(127)));
compare(&mut machine, 1);
assert!(!machine.registers.status.contains(PS_ZERO));
@ -1156,9 +1181,7 @@ fn compare_test_helper<F> (
assert!(!machine.registers.status.contains(PS_NEGATIVE));
machine.execute_instruction(
(load_instruction, OpInput::UseImmediate(1))
);
machine.execute_instruction((load_instruction, OpInput::UseImmediate(1)));
compare(&mut machine, 2);
assert!(!machine.registers.status.contains(PS_ZERO));
@ -1166,31 +1189,25 @@ fn compare_test_helper<F> (
assert!(machine.registers.status.contains(PS_NEGATIVE));
machine.execute_instruction(
(load_instruction, OpInput::UseImmediate(20))
);
machine.execute_instruction((load_instruction, OpInput::UseImmediate(20)));
compare(&mut machine, -50);
compare(&mut machine, -50i8 as u8);
assert!(!machine.registers.status.contains(PS_ZERO));
assert!(!machine.registers.status.contains(PS_CARRY));
assert!(!machine.registers.status.contains(PS_NEGATIVE));
machine.execute_instruction(
(load_instruction, OpInput::UseImmediate(1))
);
machine.execute_instruction((load_instruction, OpInput::UseImmediate(1)));
compare(&mut machine, -1);
compare(&mut machine, -1i8 as u8);
assert!(!machine.registers.status.contains(PS_ZERO));
assert!(!machine.registers.status.contains(PS_CARRY));
assert!(!machine.registers.status.contains(PS_NEGATIVE));
machine.execute_instruction(
(load_instruction, OpInput::UseImmediate(127))
);
machine.execute_instruction((load_instruction, OpInput::UseImmediate(127)));
compare(&mut machine, -128);
compare(&mut machine, -128i8 as u8);
assert!(!machine.registers.status.contains(PS_ZERO));
assert!(!machine.registers.status.contains(PS_CARRY));
assert!(machine.registers.status.contains(PS_NEGATIVE));
@ -1199,30 +1216,24 @@ fn compare_test_helper<F> (
#[test]
fn compare_with_a_register_test() {
compare_test_helper(
&mut |machine: &mut Machine, val: u8| {
machine.compare_with_a_register(val);
},
Instruction::LDA
&mut |machine: &mut Machine, val: u8| { machine.compare_with_a_register(val); },
Instruction::LDA,
);
}
#[test]
fn compare_with_x_register_test() {
compare_test_helper(
&mut |machine: &mut Machine, val: u8| {
machine.compare_with_x_register(val);
},
Instruction::LDX
&mut |machine: &mut Machine, val: u8| { machine.compare_with_x_register(val); },
Instruction::LDX,
);
}
#[test]
fn compare_with_y_register_test() {
compare_test_helper(
&mut |machine: &mut Machine, val: u8| {
machine.compare_with_y_register(val);
},
Instruction::LDY
&mut |machine: &mut Machine, val: u8| { machine.compare_with_y_register(val); },
Instruction::LDY,
);
}
@ -1230,11 +1241,9 @@ fn compare_with_y_register_test() {
fn exclusive_or_test() {
let mut machine = Machine::new();
for a_before in range_incl(0u8, 255u8) {
for val in range_incl(0u8, 255u8) {
machine.execute_instruction(
(Instruction::LDA, OpInput::UseImmediate(a_before))
);
for a_before in range_inclusive(0u8, 255u8) {
for val in range_inclusive(0u8, 255u8) {
machine.execute_instruction((Instruction::LDA, OpInput::UseImmediate(a_before)));
machine.exclusive_or(val);
@ -1260,11 +1269,9 @@ fn exclusive_or_test() {
fn inclusive_or_test() {
let mut machine = Machine::new();
for a_before in range_incl(0u8, 255u8) {
for val in range_incl(0u8, 255u8) {
machine.execute_instruction(
(Instruction::LDA, OpInput::UseImmediate(a_before))
);
for a_before in range_inclusive(0u8, 255u8) {
for val in range_inclusive(0u8, 255u8) {
machine.execute_instruction((Instruction::LDA, OpInput::UseImmediate(a_before)));
machine.inclusive_or(val);
@ -1285,3 +1292,4 @@ fn inclusive_or_test() {
}
}
}
}

View File

@ -46,12 +46,18 @@ pub const STACK_ADDRESS_HI: Address = Address(0x01FF);
pub const IRQ_INTERRUPT_VECTOR_LO: Address = Address(0xFFFE);
pub const IRQ_INTERRUPT_VECTOR_HI: Address = Address(0xFFFF);
const MEMORY_SIZE: usize = (ADDR_HI_BARE - ADDR_LO_BARE) as usize + 1us;
const MEMORY_SIZE: usize = (ADDR_HI_BARE - ADDR_LO_BARE) as usize + 1usize;
// FIXME: Should this use indirection for `bytes`?
#[derive(Copy)]
pub struct Memory {
bytes: [u8; MEMORY_SIZE]
bytes: [u8; MEMORY_SIZE],
}
impl Clone for Memory {
fn clone(&self) -> Self {
*self
}
}
impl Memory {
@ -67,8 +73,7 @@ impl Memory {
&mut self.bytes[address.to_usize()]
}
pub fn get_slice(&self, Address(start): Address,
AddressDiff(diff): AddressDiff) -> &[u8] {
pub fn get_slice(&self, Address(start): Address, AddressDiff(diff): AddressDiff) -> &[u8] {
let start = start as usize;
let diff = diff as usize;
let end = start + diff;
@ -100,4 +105,3 @@ impl Memory {
STACK_ADDRESS_LO <= *address && *address <= STACK_ADDRESS_HI
}
}

View File

@ -1,34 +0,0 @@
use std::num::Int;
pub struct RangeIncl<T: Int> {
state: Option<T>,
end: T,
}
pub fn range_incl<T: Int>(begin: T, end: T) -> RangeIncl<T> {
RangeIncl { state: Some(begin), end: end }
}
trait One : Int {
fn my_one(_: Option<Self>) -> Self {
Int::one()
}
}
impl<T> One for T where T: Int {}
impl<T: Int> Iterator for RangeIncl<T> {
type Item = T;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
match self.state {
Some(current) => {
self.state =
if current == self.end { None }
else { Some(current + One::my_one(None::<T>)) };
Some(current)
},
None => {
None
}
}
}
}

View File

@ -29,7 +29,7 @@ use address::{Address, AddressDiff};
use memory::{STACK_ADDRESS_LO, STACK_ADDRESS_HI};
// Useful for constructing Status instances
#[derive(Copy)]
#[derive(Copy, Clone)]
pub struct StatusArgs {
pub negative: bool,
pub overflow: bool,
@ -43,31 +43,32 @@ pub struct StatusArgs {
impl StatusArgs {
pub fn none() -> StatusArgs {
StatusArgs { negative: false,
StatusArgs {
negative: false,
overflow: false,
unused: false,
brk: false,
decimal_mode: false,
disable_interrupts: false,
zero: false,
carry: false, }
carry: false,
}
}
}
pub bitflags! {
#[derive(Debug)]
flags Status: u8 {
const PS_NEGATIVE = 0b10000000,
const PS_OVERFLOW = 0b01000000,
const PS_UNUSED = 0b00100000, // JAM: Should this exist?
bitflags! {
pub struct Status: u8 {
const PS_NEGATIVE = 0b10000000;
const PS_OVERFLOW = 0b01000000;
const PS_UNUSED = 0b00100000; // JAM: Should this exist?
// (note that it affects the
// behavior of things like
// from_bits_truncate)
const PS_BRK = 0b00010000,
const PS_DECIMAL_MODE = 0b00001000,
const PS_DISABLE_INTERRUPTS = 0b00000100,
const PS_ZERO = 0b00000010,
const PS_CARRY = 0b00000001,
const PS_BRK = 0b00010000;
const PS_DECIMAL_MODE = 0b00001000;
const PS_DISABLE_INTERRUPTS = 0b00000100;
const PS_ZERO = 0b00000010;
const PS_CARRY = 0b00000001;
}
}
@ -75,14 +76,16 @@ impl Status {
pub fn default() -> Status {
// TODO akeeton: Revisit these defaults.
Status::new(StatusArgs { negative: false,
Status::new(StatusArgs {
negative: false,
overflow: false,
unused: true,
brk: false,
decimal_mode: false,
disable_interrupts: true,
zero: false,
carry: false, } )
carry: false,
})
}
pub fn new(StatusArgs { negative,
@ -96,14 +99,30 @@ impl Status {
{
let mut out = Status::empty();
if negative { out = out | PS_NEGATIVE }
if overflow { out = out | PS_OVERFLOW }
if unused { out = out | PS_UNUSED }
if brk { out = out | PS_BRK }
if decimal_mode { out = out | PS_DECIMAL_MODE }
if disable_interrupts { out = out | PS_DISABLE_INTERRUPTS }
if zero { out = out | PS_ZERO }
if carry { out = out | PS_CARRY }
if negative {
out = out | PS_NEGATIVE
}
if overflow {
out = out | PS_OVERFLOW
}
if unused {
out = out | PS_UNUSED
}
if brk {
out = out | PS_BRK
}
if decimal_mode {
out = out | PS_DECIMAL_MODE
}
if disable_interrupts {
out = out | PS_DISABLE_INTERRUPTS
}
if zero {
out = out | PS_ZERO
}
if carry {
out = out | PS_CARRY
}
out
}
@ -121,12 +140,11 @@ impl Status {
}
}
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct StackPointer(pub u8);
impl StackPointer {
pub fn to_address(&self) -> Address
{
pub fn to_address(&self) -> Address {
let StackPointer(sp) = *self;
STACK_ADDRESS_LO + AddressDiff(sp as i32)
}
@ -144,14 +162,14 @@ impl StackPointer {
}
}
#[derive(Copy, PartialEq, Eq, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Registers {
pub accumulator: i8,
pub index_x: i8,
pub index_y: i8,
pub stack_pointer: StackPointer,
pub program_counter: Address,
pub status: Status
pub status: Status,
}
impl Registers {
@ -163,8 +181,7 @@ impl Registers {
index_y: 0,
stack_pointer: StackPointer(STACK_ADDRESS_HI.get_offset()),
program_counter: Address(0),
status: Status::default()
status: Status::default(),
}
}
}