Compare commits

..

2 Commits

Author SHA1 Message Date
Matthias Endler 906d6e3f19
Merge c58bba1f4c into 4847744518 2024-04-26 10:04:00 +00:00
Matthias c58bba1f4c Code Cleanup
This adds some new directives for clippy and fixes all warnings.
Also updated the dependencies to their latest versions.
2024-04-26 12:03:56 +02:00
3 changed files with 43 additions and 6 deletions

View File

@ -47,6 +47,9 @@ where
}
impl<M: Bus, V: Variant> CPU<M, V> {
// Allowing `needless_pass_by_value` to simplify construction. Passing by
// value avoids the borrow and improves readability when constructing the
// CPU.
#[allow(clippy::needless_pass_by_value)]
pub fn new(memory: M, _variant: V) -> CPU<M, V> {
CPU {
@ -638,18 +641,29 @@ impl<M: Bus, V: Variant> CPU<M, V> {
}
}
/// Checks if a given `u8` value should be interpreted as negative when
/// considered as `i8`.
///
/// In an 8-bit unsigned integer (`u8`), values range from 0 to 255. When
/// these values are interpreted as signed integers (`i8`), values from 128
/// to 255 are considered negative, corresponding to the signed range -128
/// to -1. This function checks if the provided `u8` value falls within that
/// range, effectively determining if the most significant bit is set, which
/// indicates a negative number in two's complement form.
/// ```
const fn value_is_negative(value: u8) -> bool {
value > 127
}
fn set_flags_from_u8(status: &mut Status, value: u8) {
let is_zero = value == 0;
let is_negative = Self::value_is_negative(value);
status.set_with_mask(
Status::PS_ZERO | Status::PS_NEGATIVE,
Status::new(StatusArgs {
zero: is_zero,
negative: Self::value_is_negative(value),
negative: is_negative,
..StatusArgs::none()
}),
);
@ -951,12 +965,13 @@ impl<M: Bus, V: Variant> CPU<M, V> {
*val = value_new;
let is_zero = value_new == 0;
let is_negative = Self::value_is_negative(value_new);
flags.set_with_mask(
Status::PS_NEGATIVE | Status::PS_ZERO,
Status::new(StatusArgs {
negative: Self::value_is_negative(value_new),
zero: is_zero,
negative: is_negative,
..StatusArgs::none()
}),
);
@ -1022,20 +1037,24 @@ impl<M: Bus, V: Variant> CPU<M, V> {
// ...
// The N flag contains most significant bit of the subtraction result.
fn compare(&mut self, r: u8, val: u8) {
// Setting the CARRY flag: A (unsigned) >= NUM (unsigned)
if r >= val {
self.registers.status.insert(Status::PS_CARRY);
} else {
self.registers.status.remove(Status::PS_CARRY);
}
// Setting the ZERO flag: A = NUM
if r == val {
self.registers.status.insert(Status::PS_ZERO);
} else {
self.registers.status.remove(Status::PS_ZERO);
}
let diff: i8 = (r as i8).wrapping_sub(val as i8);
if diff < 0 {
// Set the NEGATIVE flag based on the MSB of the result of subtraction
// This checks if the 8th bit is set (0x80 in hex is 128 in decimal, which is the 8th bit in a byte)
let diff = r.wrapping_sub(val);
if Self::value_is_negative(diff) {
self.registers.status.insert(Status::PS_NEGATIVE);
} else {
self.registers.status.remove(Status::PS_NEGATIVE);
@ -1101,6 +1120,11 @@ impl<M: Bus, V: Variant> core::fmt::Debug for CPU<M, V> {
#[cfg(test)]
mod tests {
// Casting from signed to unsigned integers is intentional in these tests
#![allow(clippy::cast_sign_loss)]
// Operations may intentionally wrap due to emulation of 8-bit unsigned
// integer arithmetic. We do this to test wrap-around conditions.
#![allow(clippy::cast_possible_wrap)]
use super::*;
use crate::instruction::Nmos6502;
@ -1204,6 +1228,8 @@ mod tests {
assert!(!cpu.registers.status.contains(Status::PS_NEGATIVE));
assert!(!cpu.registers.status.contains(Status::PS_OVERFLOW));
// Allow casting from i8 to u8; -127i8 wraps to 129u8, as intended for
// two's complement arithmetic.
cpu.add_with_carry(-127i8 as u8);
assert_eq!(cpu.registers.accumulator, 0);
assert!(cpu.registers.status.contains(Status::PS_CARRY));

View File

@ -500,6 +500,7 @@ impl crate::Variant for RevisionA {
}
/// Emulates the 65C02, which has a few bugfixes, and another addressing mode
#[derive(Copy, Clone, Debug)]
pub struct Cmos6502;
impl crate::Variant for Cmos6502 {

View File

@ -81,6 +81,14 @@ pub trait Bus {
/// Sets the bytes starting at the given address to the given values.
///
/// This is a default implementation that calls `set_byte` for each byte.
///
/// # Note
///
/// This assumes that the length of `values` is less than or equal to
/// [`u16::MAX`] (65535). If the length of `values` is greater than `u16::MAX`,
/// this will truncate the length. This assumption is made because the
/// maximum addressable memory for the 6502 is 64KB.
#[allow(clippy::cast_possible_truncation)]
fn set_bytes(&mut self, start: u16, values: &[u8]) {
for i in 0..values.len() as u16 {
self.set_byte(start + i, values[i as usize]);
@ -102,12 +110,14 @@ impl Bus for Memory {
self.bytes[address as usize]
}
// Sets the byte at the given address to the given value and returns the
// previous value at the address.
/// Sets the byte at the given address to the given value and returns the
/// previous value at the address.
fn set_byte(&mut self, address: u16, value: u8) {
self.bytes[address as usize] = value;
}
/// Fast way to set multiple bytes in memory when the underlying memory is a
/// consecutive block of bytes.
fn set_bytes(&mut self, start: u16, values: &[u8]) {
let start = start as usize;