1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-25 18:30:21 +00:00
CLK/Processors/6502Esque/Implementation/LazyFlags.hpp

84 lines
2.3 KiB
C++

//
// LazyFlags.hpp
// Clock Signal
//
// Created by Thomas Harte on 05/10/2020.
// Copyright © 2020 Thomas Harte. All rights reserved.
//
#ifndef LazyFlags_h
#define LazyFlags_h
#include "../6502Esque.hpp"
namespace CPU {
namespace MOS6502Esque {
struct LazyFlags {
/// Bit 7 is set if the negative flag is set; otherwise it is clear.
uint8_t negative_result = 0;
/// Non-zero if the zero flag is clear, zero if it is set.
uint8_t zero_result = 0;
/// Contains Flag::Carry.
uint8_t carry = 0;
/// Contains Flag::Decimal.
uint8_t decimal = 0;
/// Contains Flag::Overflow.
uint8_t overflow = 0;
/// Contains Flag::Interrupt, complemented.
uint8_t inverse_interrupt = 0;
/// Sets N and Z flags per the 8-bit value @c value.
void set_nz(uint8_t value) {
zero_result = negative_result = value;
}
/// Sets N and Z flags per the 8- or 16-bit value @c value; @c shift should be 0 to indicate an 8-bit value or 8 to indicate a 16-bit value.
void set_nz(uint16_t value, int shift) {
negative_result = uint8_t(value >> shift);
zero_result = uint8_t(value | (value >> shift));
}
/// Sets the Z flag per the 8- or 16-bit value @c value; @c shift should be 0 to indicate an 8-bit value or 8 to indicate a 16-bit value.
void set_z(uint16_t value, int shift) {
zero_result = uint8_t(value | (value >> shift));
}
/// Sets the N flag per the 8- or 16-bit value @c value; @c shift should be 0 to indicate an 8-bit value or 8 to indicate a 16-bit value.
void set_n(uint16_t value, int shift) {
negative_result = uint8_t(value >> shift);
}
void set(uint8_t flags) {
carry = flags & Flag::Carry;
negative_result = flags & Flag::Sign;
zero_result = (~flags) & Flag::Zero;
overflow = flags & Flag::Overflow;
inverse_interrupt = (~flags) & Flag::Interrupt;
decimal = flags & Flag::Decimal;
}
uint8_t get() const {
return carry | overflow | (inverse_interrupt ^ Flag::Interrupt) | (negative_result & 0x80) | (zero_result ? 0 : Flag::Zero) | Flag::Always | decimal;
}
LazyFlags() {
// Only the interrupt flag is defined upon reset but get_flags isn't going to
// mask the other flags so we need to do that, at least.
carry &= Flag::Carry;
decimal &= Flag::Decimal;
overflow &= Flag::Overflow;
}
};
}
}
#endif /* LazyFlags_h */