Try and sort out problematic "noexcept" specifications (mainly due to events)

This commit is contained in:
Adrian Conlon 2024-01-13 10:24:21 +00:00
parent 63e958e069
commit 4e536ee7ed
14 changed files with 127 additions and 123 deletions

View File

@ -16,15 +16,15 @@ namespace EightBit {
protected:
BigEndianProcessor(Bus& memory) noexcept;
[[nodiscard]] register16_t getWord() noexcept override;
void setWord(register16_t value) noexcept override;
[[nodiscard]] register16_t getWord() override;
void setWord(register16_t value) override;
[[nodiscard]] register16_t getWordPaged(uint8_t page, uint8_t offset) noexcept override;
void setWordPaged(uint8_t page, uint8_t offset, register16_t value) noexcept override;
[[nodiscard]] register16_t getWordPaged(uint8_t page, uint8_t offset) override;
void setWordPaged(uint8_t page, uint8_t offset, register16_t value) override;
[[nodiscard]] register16_t fetchWord() noexcept final;
[[nodiscard]] register16_t fetchWord() final;
void pushWord(register16_t value) noexcept final;
[[nodiscard]] register16_t popWord() noexcept final;
void pushWord(register16_t value) final;
[[nodiscard]] register16_t popWord() final;
};
}

View File

@ -12,7 +12,7 @@
namespace EightBit {
class Bus : public Mapper {
public:
virtual ~Bus() noexcept {};
virtual ~Bus() noexcept = default;
Signal<EventArgs> WritingByte;
Signal<EventArgs> WrittenByte;
@ -33,15 +33,15 @@ namespace EightBit {
virtual void poke(const uint16_t address, const uint8_t value) noexcept { reference(address) = value; }
void poke(const register16_t address, const uint8_t value) noexcept { poke(address.word, value); }
[[nodiscard]] uint8_t read() noexcept;
[[nodiscard]] uint8_t read();
template<class T> [[nodiscard]] auto read(const T address) {
ADDRESS() = address;
return read();
}
void write() noexcept;
void write(uint8_t value) noexcept;
template<class T> void write(const T offset, const uint8_t value) noexcept {
void write();
void write(uint8_t value);
template<class T> void write(const T offset, const uint8_t value) {
ADDRESS() = offset;
write(value);
}
@ -56,7 +56,7 @@ namespace EightBit {
[[nodiscard]] auto& reference(const register16_t address) noexcept { return reference(address.word); }
[[nodiscard]] uint8_t& reference() noexcept { return reference(ADDRESS()); }
void loadHexFile(std::string path);
void loadHexFile(const std::string& path);
private:
uint8_t m_data = Chip::Mask8;

View File

@ -10,17 +10,17 @@
Signal<EventArgs> Lowered ## name;
#define DECLARE_PIN_LEVEL_RAISE(name) \
virtual void raise ## name() noexcept;
virtual void raise ## name();
#define DECLARE_PIN_LEVEL_LOWER(name) \
virtual void lower ## name() noexcept;
virtual void lower ## name();
#define DECLARE_PIN_LEVEL_CHANGERS(name) \
DECLARE_PIN_LEVEL_RAISE(name) \
DECLARE_PIN_LEVEL_LOWER(name)
#define DEFINE_PIN_LEVEL_RAISE(name, within) \
void EightBit:: within ::raise ## name() noexcept { \
void EightBit:: within ::raise ## name() { \
if (lowered( name ())) { \
Raising ## name.fire(); \
raise( name ()); \
@ -29,7 +29,7 @@
}
#define DEFINE_PIN_LEVEL_LOWER(name, within) \
void EightBit:: within ::lower ## name() noexcept { \
void EightBit:: within ::lower ## name() { \
if (raised( name ())) { \
Lowering ## name.fire(); \
lower( name ()); \
@ -106,7 +106,7 @@ namespace EightBit {
static constexpr void flip(PinLevel& out) noexcept { match(out, out == PinLevel::Low ? PinLevel::High : PinLevel::Low); }
virtual ~Device() noexcept {};
virtual ~Device() noexcept = default;
Device(const Device& rhs) noexcept;
bool operator==(const Device& rhs) const noexcept;

View File

@ -44,8 +44,8 @@ namespace EightBit {
}
};
IntelProcessor(const IntelProcessor& rhs);
bool operator==(const IntelProcessor& rhs) const;
IntelProcessor(const IntelProcessor& rhs) noexcept;
bool operator==(const IntelProcessor& rhs) const noexcept;
[[nodiscard]] constexpr const auto& getDecodedOpcode(const size_t i) const noexcept {
return m_decodedOpcodes[i];
@ -138,27 +138,27 @@ namespace EightBit {
return calculateHalfCarry(m_halfCarryTableSub, before, value, calculation);
}
void handleRESET() noexcept override;
void handleRESET() override;
void push(uint8_t value) noexcept final;
[[nodiscard]] uint8_t pop() noexcept final;
void push(uint8_t value) final;
[[nodiscard]] uint8_t pop() final;
//
[[nodiscard]] register16_t getWord() noexcept final;
void setWord(register16_t value) noexcept final;
[[nodiscard]] register16_t getWord() final;
void setWord(register16_t value) final;
//
virtual void restart(uint8_t address) noexcept;
virtual int callConditional(int condition) noexcept;
virtual int jumpConditional(int condition) noexcept;
virtual int returnConditional(int condition) noexcept;
virtual void restart(uint8_t address);
virtual int callConditional(int condition);
virtual int jumpConditional(int condition);
virtual int returnConditional(int condition);
virtual void jr(int8_t offset) noexcept;
virtual int jrConditional(int condition) noexcept;
void ret() noexcept override;
virtual int jrConditional(int condition);
void ret() override;
void resetWorkingRegisters();
void resetWorkingRegisters() noexcept;
private:
static std::array<int, 8> m_halfCarryTableAdd;

View File

@ -8,23 +8,23 @@ namespace EightBit {
class LittleEndianProcessor : public Processor {
public:
LittleEndianProcessor(const LittleEndianProcessor& rhs);
LittleEndianProcessor(const LittleEndianProcessor& rhs) noexcept;
[[nodiscard]] register16_t peekWord(register16_t address) noexcept final;
void pokeWord(register16_t address, register16_t value) noexcept final;
protected:
LittleEndianProcessor(Bus& memory);
LittleEndianProcessor(Bus& memory) noexcept;
[[nodiscard]] register16_t getWord() noexcept override;
void setWord(register16_t value) noexcept override;
[[nodiscard]] register16_t getWord() override;
void setWord(register16_t value) override;
[[nodiscard]] register16_t getWordPaged(uint8_t page, uint8_t offset) noexcept override;
void setWordPaged(uint8_t page, uint8_t offset, register16_t value) noexcept override;
[[nodiscard]] register16_t getWordPaged(uint8_t page, uint8_t offset) override;
void setWordPaged(uint8_t page, uint8_t offset, register16_t value) override;
[[nodiscard]] register16_t fetchWord() noexcept final;
[[nodiscard]] register16_t fetchWord() final;
void pushWord(register16_t value) noexcept override;
[[nodiscard]] register16_t popWord() noexcept override;
void pushWord(register16_t value) override;
[[nodiscard]] register16_t popWord() override;
};
}

View File

@ -14,6 +14,8 @@ namespace EightBit {
// *) Possibly 'reference'able (Very likely if you've exposed 'poke')
class Memory {
public:
virtual ~Memory() = default;
[[nodiscard]] virtual uint16_t size() const noexcept = 0;
[[nodiscard]] virtual uint8_t peek(uint16_t address) const noexcept = 0;

View File

@ -21,8 +21,8 @@ namespace EightBit {
return result;
}
Processor(const Processor& rhs);
bool operator==(const Processor& rhs) const;
Processor(const Processor& rhs) noexcept;
bool operator==(const Processor& rhs) const noexcept;
[[nodiscard]] constexpr auto& PC() noexcept { return m_pc; }
[[nodiscard]] constexpr const auto& PC() const noexcept { return m_pc; }
@ -44,44 +44,44 @@ namespace EightBit {
[[nodiscard]] constexpr auto& opcode() noexcept { return m_opcode; }
[[nodiscard]] constexpr auto& BUS() noexcept { return m_bus; }
virtual void handleRESET() noexcept;
virtual void handleINT() noexcept;
virtual void handleRESET();
virtual void handleINT();
void memoryWrite(register16_t address, uint8_t data) noexcept;
void memoryWrite(register16_t address) noexcept;
void memoryWrite(uint8_t data) noexcept;
virtual void memoryWrite() noexcept;
virtual void busWrite() noexcept;
void memoryWrite(register16_t address, uint8_t data);
void memoryWrite(register16_t address);
void memoryWrite(uint8_t data);
virtual void memoryWrite();
virtual void busWrite();
uint8_t memoryRead(register16_t address) noexcept;
virtual uint8_t memoryRead() noexcept;
virtual uint8_t busRead() noexcept;
uint8_t memoryRead(register16_t address);
virtual uint8_t memoryRead();
virtual uint8_t busRead();
uint8_t getBytePaged(uint8_t page, uint8_t offset) noexcept;
void setBytePaged(uint8_t page, uint8_t offset, uint8_t value) noexcept;
uint8_t getBytePaged(uint8_t page, uint8_t offset);
void setBytePaged(uint8_t page, uint8_t offset, uint8_t value);
uint8_t fetchByte() noexcept;
uint8_t fetchByte();
[[nodiscard]] virtual register16_t getWord() noexcept = 0;
virtual void setWord(register16_t value) noexcept = 0;
[[nodiscard]] virtual register16_t getWord() = 0;
virtual void setWord(register16_t value) = 0;
[[nodiscard]] virtual register16_t getWordPaged(uint8_t page, uint8_t offset) noexcept = 0;
virtual void setWordPaged(uint8_t page, uint8_t offset, register16_t value) noexcept = 0;
[[nodiscard]] virtual register16_t getWordPaged(uint8_t page, uint8_t offset) = 0;
virtual void setWordPaged(uint8_t page, uint8_t offset, register16_t value) = 0;
[[nodiscard]] virtual register16_t fetchWord() noexcept = 0;
[[nodiscard]] virtual register16_t fetchWord() = 0;
virtual void push(uint8_t value) noexcept = 0;
[[nodiscard]] virtual uint8_t pop() noexcept = 0;
virtual void push(uint8_t value) = 0;
[[nodiscard]] virtual uint8_t pop() = 0;
virtual void pushWord(register16_t value) noexcept = 0;
[[nodiscard]] virtual register16_t popWord() noexcept = 0;
virtual void pushWord(register16_t value) = 0;
[[nodiscard]] virtual register16_t popWord() = 0;
[[nodiscard]] register16_t getWord(register16_t address) noexcept;
void setWord(register16_t address, register16_t value) noexcept;
[[nodiscard]] register16_t getWord(register16_t address);
void setWord(register16_t address, register16_t value);
void jump(const register16_t destination) noexcept;
virtual void call(register16_t destination) noexcept;
virtual void ret() noexcept;
virtual void call(register16_t destination);
virtual void ret();
private:
Bus& m_bus;

View File

@ -8,6 +8,7 @@ namespace EightBit {
class Ram : public Rom {
public:
Ram(size_t size = 0) noexcept;
virtual ~Ram() = default;
[[nodiscard]] uint8_t& reference(uint16_t address) noexcept final;
void poke(uint16_t address, uint8_t value) noexcept final;

View File

@ -27,6 +27,7 @@ namespace EightBit {
Rom(size_t size = 0) noexcept;
Rom(const Rom& rhs);
virtual ~Rom() = default;
Rom& operator=(const Rom& rhs);
bool operator==(const Rom& rhs) const;
@ -41,7 +42,7 @@ namespace EightBit {
const auto size = end - start;
if (limit < 0)
limit = static_cast<int>(size - readOffset);
limit = static_cast<int>(size) - readOffset;
const size_t extent = static_cast<size_t>(limit) + writeOffset;
if (m_bytes.size() < extent)

View File

@ -4,44 +4,44 @@
EightBit::BigEndianProcessor::BigEndianProcessor(Bus& memory) noexcept
: Processor(memory) {}
EightBit::register16_t EightBit::BigEndianProcessor::getWord() noexcept {
EightBit::register16_t EightBit::BigEndianProcessor::getWord() {
const auto high = memoryRead();
++BUS().ADDRESS();
const auto low = memoryRead();
return { low, high };
}
void EightBit::BigEndianProcessor::setWord(const register16_t value) noexcept {
void EightBit::BigEndianProcessor::setWord(const register16_t value) {
memoryWrite(value.high);
++BUS().ADDRESS();
memoryWrite(value.low);
}
EightBit::register16_t EightBit::BigEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) noexcept {
EightBit::register16_t EightBit::BigEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) {
const auto high = getBytePaged(page, offset);
++BUS().ADDRESS().low;
const auto low = memoryRead();
return { low, high };
}
void EightBit::BigEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) noexcept {
void EightBit::BigEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) {
setBytePaged(page, offset, value.high);
++BUS().ADDRESS().low;
memoryWrite(value.low);
}
EightBit::register16_t EightBit::BigEndianProcessor::fetchWord() noexcept {
EightBit::register16_t EightBit::BigEndianProcessor::fetchWord() {
const auto high = fetchByte();
const auto low = fetchByte();
return { low, high };
}
void EightBit::BigEndianProcessor::pushWord(const register16_t value) noexcept {
void EightBit::BigEndianProcessor::pushWord(const register16_t value) {
push(value.low);
push(value.high);
}
EightBit::register16_t EightBit::BigEndianProcessor::popWord() noexcept {
EightBit::register16_t EightBit::BigEndianProcessor::popWord() {
const auto high = pop();
const auto low = pop();
return { low, high };

View File

@ -8,25 +8,25 @@ void EightBit::Bus::raisePOWER() noexcept {}
void EightBit::Bus::lowerPOWER() noexcept {}
uint8_t EightBit::Bus::read() noexcept {
uint8_t EightBit::Bus::read() {
ReadingByte.fire();
const auto returned = DATA() = reference();
ReadByte.fire();
return returned;
}
void EightBit::Bus::write() noexcept {
void EightBit::Bus::write() {
WritingByte.fire();
reference() = DATA();
WrittenByte.fire();
}
void EightBit::Bus::write(const uint8_t value) noexcept {
void EightBit::Bus::write(const uint8_t value) {
DATA() = value;
write();
}
void EightBit::Bus::loadHexFile(const std::string path) {
void EightBit::Bus::loadHexFile(const std::string& path) {
IntelHexFile file(path);
const auto chunks = file.parse();
for (const auto& chunk : chunks) {

View File

@ -19,7 +19,7 @@ EightBit::IntelProcessor::IntelProcessor(Bus& bus)
});
}
EightBit::IntelProcessor::IntelProcessor(const IntelProcessor& rhs)
EightBit::IntelProcessor::IntelProcessor(const IntelProcessor& rhs) noexcept
: LittleEndianProcessor(rhs) {
m_sp = rhs.m_sp;
@ -28,55 +28,55 @@ EightBit::IntelProcessor::IntelProcessor(const IntelProcessor& rhs)
HALT() = rhs.HALT();
}
void EightBit::IntelProcessor::resetWorkingRegisters() {
void EightBit::IntelProcessor::resetWorkingRegisters() noexcept {
AF() = BC() = DE() = HL() = Mask16;
}
DEFINE_PIN_LEVEL_CHANGERS(HALT, IntelProcessor);
void EightBit::IntelProcessor::handleRESET() noexcept {
void EightBit::IntelProcessor::handleRESET() {
Processor::handleRESET();
PC() = 0;
}
void EightBit::IntelProcessor::push(const uint8_t value) noexcept {
void EightBit::IntelProcessor::push(const uint8_t value) {
memoryWrite(--SP(), value);
}
uint8_t EightBit::IntelProcessor::pop() noexcept {
uint8_t EightBit::IntelProcessor::pop() {
return memoryRead(SP()++);
}
EightBit::register16_t EightBit::IntelProcessor::getWord() noexcept {
EightBit::register16_t EightBit::IntelProcessor::getWord() {
const auto returned = LittleEndianProcessor::getWord();
MEMPTR() = BUS().ADDRESS();
return returned;
}
void EightBit::IntelProcessor::setWord(const register16_t value) noexcept {
void EightBit::IntelProcessor::setWord(const register16_t value) {
LittleEndianProcessor::setWord(value);
MEMPTR() = BUS().ADDRESS();
}
void EightBit::IntelProcessor::restart(const uint8_t address) noexcept {
void EightBit::IntelProcessor::restart(const uint8_t address) {
call(MEMPTR() = { address, 0 });
}
int EightBit::IntelProcessor::callConditional(const int condition) noexcept {
int EightBit::IntelProcessor::callConditional(const int condition) {
MEMPTR() = fetchWord();
if (condition)
call(MEMPTR());
return condition;
}
int EightBit::IntelProcessor::jumpConditional(const int condition) noexcept {
int EightBit::IntelProcessor::jumpConditional(const int condition) {
MEMPTR() = fetchWord();
if (condition)
jump(MEMPTR());
return condition;
}
int EightBit::IntelProcessor::returnConditional(const int condition) noexcept {
int EightBit::IntelProcessor::returnConditional(const int condition) {
if (condition)
ret();
return condition;
@ -86,7 +86,7 @@ void EightBit::IntelProcessor::jr(const int8_t offset) noexcept {
jump(MEMPTR() = PC() + offset);
}
int EightBit::IntelProcessor::jrConditional(const int condition) noexcept {
int EightBit::IntelProcessor::jrConditional(const int condition) {
const auto offsetAddress = PC()++;
if (condition) {
const auto offset = memoryRead(offsetAddress);
@ -95,12 +95,12 @@ int EightBit::IntelProcessor::jrConditional(const int condition) noexcept {
return condition;
}
void EightBit::IntelProcessor::ret() noexcept {
void EightBit::IntelProcessor::ret() {
Processor::ret();
MEMPTR() = PC();
}
bool EightBit::IntelProcessor::operator==(const EightBit::IntelProcessor& rhs) const {
bool EightBit::IntelProcessor::operator==(const EightBit::IntelProcessor& rhs) const noexcept {
return
Processor::operator==(rhs)
&& HALT() == rhs.HALT()

View File

@ -1,50 +1,50 @@
#include "stdafx.h"
#include "../inc/LittleEndianProcessor.h"
EightBit::LittleEndianProcessor::LittleEndianProcessor(Bus& memory)
EightBit::LittleEndianProcessor::LittleEndianProcessor(Bus& memory) noexcept
: Processor(memory) {}
EightBit::LittleEndianProcessor::LittleEndianProcessor(const LittleEndianProcessor& rhs)
EightBit::LittleEndianProcessor::LittleEndianProcessor(const LittleEndianProcessor& rhs) noexcept
: Processor(rhs) {}
EightBit::register16_t EightBit::LittleEndianProcessor::getWord() noexcept {
EightBit::register16_t EightBit::LittleEndianProcessor::getWord() {
const auto low = memoryRead();
++BUS().ADDRESS();
const auto high = memoryRead();
return { low, high };
}
void EightBit::LittleEndianProcessor::setWord(const register16_t value) noexcept {
void EightBit::LittleEndianProcessor::setWord(const register16_t value) {
memoryWrite(value.low);
++BUS().ADDRESS();
memoryWrite(value.high);
}
EightBit::register16_t EightBit::LittleEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) noexcept {
EightBit::register16_t EightBit::LittleEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) {
const auto low = getBytePaged(page, offset);
++BUS().ADDRESS().low;
const auto high = memoryRead();
return { low, high };
}
void EightBit::LittleEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) noexcept {
void EightBit::LittleEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) {
setBytePaged(page, offset, value.low);
++BUS().ADDRESS().low;
memoryWrite(value.high);
}
EightBit::register16_t EightBit::LittleEndianProcessor::fetchWord() noexcept {
EightBit::register16_t EightBit::LittleEndianProcessor::fetchWord() {
const auto low = fetchByte();
const auto high = fetchByte();
return { low, high };
}
void EightBit::LittleEndianProcessor::pushWord(const register16_t value) noexcept {
void EightBit::LittleEndianProcessor::pushWord(const register16_t value) {
push(value.high);
push(value.low);
}
EightBit::register16_t EightBit::LittleEndianProcessor::popWord() noexcept {
EightBit::register16_t EightBit::LittleEndianProcessor::popWord() {
const auto low = pop();
const auto high = pop();
return { low, high };

View File

@ -5,7 +5,7 @@ EightBit::Processor::Processor(Bus& bus) noexcept
: m_bus(bus) {
}
EightBit::Processor::Processor(const Processor& rhs)
EightBit::Processor::Processor(const Processor& rhs) noexcept
: ClockedChip(rhs),
m_bus(rhs.m_bus) {
RESET() = rhs.RESET();
@ -16,68 +16,68 @@ EightBit::Processor::Processor(const Processor& rhs)
DEFINE_PIN_LEVEL_CHANGERS(RESET, Processor)
DEFINE_PIN_LEVEL_CHANGERS(INT, Processor)
void EightBit::Processor::handleRESET() noexcept {
void EightBit::Processor::handleRESET() {
raiseRESET();
}
void EightBit::Processor::handleINT() noexcept {
void EightBit::Processor::handleINT() {
raiseINT();
}
void EightBit::Processor::memoryWrite(const register16_t address, const uint8_t data) noexcept {
void EightBit::Processor::memoryWrite(const register16_t address, const uint8_t data) {
BUS().ADDRESS() = address;
memoryWrite(data);
}
void EightBit::Processor::memoryWrite(const register16_t address) noexcept {
void EightBit::Processor::memoryWrite(const register16_t address) {
BUS().ADDRESS() = address;
memoryWrite();
}
void EightBit::Processor::memoryWrite(const uint8_t data) noexcept {
void EightBit::Processor::memoryWrite(const uint8_t data) {
BUS().DATA() = data;
memoryWrite();
}
void EightBit::Processor::memoryWrite() noexcept {
void EightBit::Processor::memoryWrite() {
busWrite();
}
void EightBit::Processor::busWrite() noexcept {
void EightBit::Processor::busWrite() {
BUS().write();
}
uint8_t EightBit::Processor::memoryRead(const register16_t address) noexcept {
uint8_t EightBit::Processor::memoryRead(const register16_t address) {
BUS().ADDRESS() = address;
return memoryRead();
}
uint8_t EightBit::Processor::memoryRead() noexcept {
uint8_t EightBit::Processor::memoryRead() {
return busRead();
}
uint8_t EightBit::Processor::busRead() noexcept {
uint8_t EightBit::Processor::busRead() {
return BUS().read();
}
uint8_t EightBit::Processor::getBytePaged(const uint8_t page, const uint8_t offset) noexcept {
uint8_t EightBit::Processor::getBytePaged(const uint8_t page, const uint8_t offset) {
return memoryRead(register16_t(offset, page));
}
void EightBit::Processor::setBytePaged(const uint8_t page, const uint8_t offset, const uint8_t value) noexcept {
void EightBit::Processor::setBytePaged(const uint8_t page, const uint8_t offset, const uint8_t value) {
memoryWrite(register16_t(offset, page), value);
}
uint8_t EightBit::Processor::fetchByte() noexcept {
uint8_t EightBit::Processor::fetchByte() {
return memoryRead(PC()++);
}
EightBit::register16_t EightBit::Processor::getWord(const register16_t address) noexcept {
EightBit::register16_t EightBit::Processor::getWord(const register16_t address) {
BUS().ADDRESS() = address;
return getWord();
}
void EightBit::Processor::setWord(const register16_t address, const register16_t value) noexcept {
void EightBit::Processor::setWord(const register16_t address, const register16_t value) {
BUS().ADDRESS() = address;
setWord(value);
}
@ -98,16 +98,16 @@ void EightBit::Processor::jump(const register16_t destination) noexcept {
PC() = destination;
}
void EightBit::Processor::call(const register16_t destination) noexcept {
void EightBit::Processor::call(const register16_t destination) {
pushWord(PC());
jump(destination);
}
void EightBit::Processor::ret() noexcept {
void EightBit::Processor::ret() {
jump(popWord());
}
bool EightBit::Processor::operator==(const EightBit::Processor& rhs) const {
bool EightBit::Processor::operator==(const EightBit::Processor& rhs) const noexcept {
return
ClockedChip::operator==(rhs)
&& RESET() == rhs.RESET()