hg80 1.0.0

Z80 and Z80N CPU core, stepped one clock edge at a time
Documentation
// Portions of this file are derived from the T80 Z80-compatible microprocessor core,
// Copyright (c) 2001-2002 Daniel Wallner, and from the T80N modifications made for the
// ZX Spectrum Next Project, Copyright 2020 Fabio Belavenuto, Victor Trucco, Charlie Ingley,
// Garry Lancaster, ACX. Redistributed under the three-clause BSD licence reproduced in NOTICE.

//! Flag rules that belong to the instruction rather than to the ALU.

use super::{Cpu, wide_value};
use crate::consts::flag;
use crate::flags;
use crate::mcode::Decoded;

impl Cpu {
    pub(super) fn undocumented_carry_source(&self, accumulator: u8, flags: u8) -> u8 {
        flags::undocumented_carry_source(self.undocumented_flags, accumulator, flags)
    }

    pub(super) fn accumulator_flag_instructions(&mut self, decoded: &Decoded) {
        let accumulator = self.accumulator();
        let mut flags = self.flags();

        if decoded.i_cpl() {
            let complemented = !accumulator;
            self.registers.af = wide_value(complemented, flags);
            flags = Self::take_undocumented(self.flags(), !accumulator);
            flags |= flag::H_MASK | flag::N_MASK;
            self.set_flags(flags);
        }
        if decoded.i_ccf() {
            let carry = flags & flag::C_MASK != 0;
            let reported = self.undocumented_carry_source(accumulator, flags);
            flags = Self::take_undocumented(flags, reported) & !(flag::N_MASK | flag::H_MASK);
            if carry {
                flags |= flag::H_MASK;
                flags &= !flag::C_MASK;
            } else {
                flags |= flag::C_MASK;
            }
            self.set_flags(flags);
        }
        if decoded.i_scf() {
            let reported = self.undocumented_carry_source(accumulator, flags);
            flags = Self::take_undocumented(flags, reported) & !(flag::N_MASK | flag::H_MASK);
            flags |= flag::C_MASK;
            self.set_flags(flags);
        }
    }

    pub(super) fn report_byte(flags: u8, value: u8, parity: bool) -> u8 {
        flags::report_byte(flags, value, parity)
    }
}