mirror of
https://github.com/FrancescoRigoni/Lib65816.git
synced 2024-09-29 09:54:44 +00:00
256 lines
6.3 KiB
C++
256 lines
6.3 KiB
C++
|
/*
|
||
|
* This file is part of the 65816 Emulator Library.
|
||
|
* Copyright (c) 2018 Francesco Rigoni.
|
||
|
*
|
||
|
* https://github.com/FrancescoRigoni/Lib65816
|
||
|
*
|
||
|
* This program is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation, version 3.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful, but
|
||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#include "CpuStatus.hpp"
|
||
|
#include "Log.hpp"
|
||
|
#include "Binary.hpp"
|
||
|
|
||
|
#define LOG_TAG "CpuStatus"
|
||
|
|
||
|
/* **********************************************
|
||
|
*
|
||
|
* Flags:
|
||
|
*
|
||
|
* b flag: the break flag
|
||
|
* c flag: the carry flag
|
||
|
* d flag: the decimal mode flag
|
||
|
* e flag: the emulation mode flag
|
||
|
* i flag: the interrupt disable flag
|
||
|
* m flag: the accumulator and memory width flag
|
||
|
* n flag: the negative flag
|
||
|
* v flag: the overflow flag
|
||
|
* x flag: the index register width flag
|
||
|
* z flag: the zero flag
|
||
|
*
|
||
|
* **********************************************/
|
||
|
|
||
|
#define STATUS_CARRY 0x01
|
||
|
#define STATUS_ZERO 0x02
|
||
|
#define STATUS_INTERRUPT_DISABLE 0x04
|
||
|
#define STATUS_DECIMAL 0x08
|
||
|
|
||
|
// In emulation mode
|
||
|
#define STATUS_BREAK 0X10
|
||
|
// In native mode (x = 0, 16 bit)
|
||
|
#define STATUS_INDEX_WIDTH 0X10
|
||
|
// Only used in native mode
|
||
|
#define STATUS_ACCUMULATOR_WIDTH 0X20
|
||
|
|
||
|
#define STATUS_OVERFLOW 0X40
|
||
|
#define STATUS_SIGN 0X80
|
||
|
|
||
|
CpuStatus::CpuStatus() {
|
||
|
}
|
||
|
|
||
|
void CpuStatus::setZeroFlag() {
|
||
|
mZeroFlag = true;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::setSignFlag() {
|
||
|
mSignFlag = true;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::setDecimalFlag() {
|
||
|
mDecimalFlag = true;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::setInterruptDisableFlag() {
|
||
|
mInterruptDisableFlag = true;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::setAccumulatorWidthFlag() {
|
||
|
mAccumulatorWidthFlag = true;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::setIndexWidthFlag() {
|
||
|
mIndexWidthFlag = true;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::setCarryFlag() {
|
||
|
mCarryFlag = true;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::setEmulationFlag() {
|
||
|
mEmulationFlag = true;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::clearZeroFlag() {
|
||
|
mZeroFlag = false;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::clearSignFlag() {
|
||
|
mSignFlag = false;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::clearDecimalFlag() {
|
||
|
mDecimalFlag = false;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::clearInterruptDisableFlag() {
|
||
|
mInterruptDisableFlag = false;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::clearAccumulatorWidthFlag() {
|
||
|
mAccumulatorWidthFlag = false;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::clearIndexWidthFlag() {
|
||
|
mIndexWidthFlag = false;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::clearCarryFlag() {
|
||
|
mCarryFlag = false;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::clearEmulationFlag() {
|
||
|
mEmulationFlag = false;
|
||
|
}
|
||
|
|
||
|
bool CpuStatus::zeroFlag() {
|
||
|
return mZeroFlag;
|
||
|
}
|
||
|
|
||
|
bool CpuStatus::signFlag() {
|
||
|
return mSignFlag;
|
||
|
}
|
||
|
|
||
|
bool CpuStatus::decimalFlag() {
|
||
|
return mDecimalFlag;
|
||
|
}
|
||
|
|
||
|
bool CpuStatus::interruptDisableFlag() {
|
||
|
return mInterruptDisableFlag;
|
||
|
}
|
||
|
|
||
|
bool CpuStatus::accumulatorWidthFlag() {
|
||
|
return mAccumulatorWidthFlag;
|
||
|
}
|
||
|
|
||
|
bool CpuStatus::indexWidthFlag() {
|
||
|
return mIndexWidthFlag;
|
||
|
}
|
||
|
|
||
|
bool CpuStatus::carryFlag() {
|
||
|
return mCarryFlag;
|
||
|
}
|
||
|
|
||
|
bool CpuStatus::emulationFlag() {
|
||
|
return mEmulationFlag;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::setBreakFlag() {
|
||
|
mBreakFlag = true;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::clearBreakFlag() {
|
||
|
mBreakFlag = false;
|
||
|
}
|
||
|
|
||
|
bool CpuStatus::breakFlag() {
|
||
|
return mBreakFlag;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::setOverflowFlag() {
|
||
|
mOverflowFlag = true;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::clearOverflowFlag() {
|
||
|
mOverflowFlag = false;
|
||
|
}
|
||
|
|
||
|
bool CpuStatus::overflowFlag() {
|
||
|
return mOverflowFlag;
|
||
|
}
|
||
|
|
||
|
uint8_t CpuStatus::getRegisterValue() {
|
||
|
uint8_t value = 0;
|
||
|
if (carryFlag()) value |= STATUS_CARRY;
|
||
|
if (zeroFlag()) value |= STATUS_ZERO;
|
||
|
if (interruptDisableFlag()) value |= STATUS_INTERRUPT_DISABLE;
|
||
|
if (decimalFlag()) value |= STATUS_DECIMAL;
|
||
|
if (emulationFlag() && breakFlag()) value |= STATUS_BREAK;
|
||
|
if (!emulationFlag() && indexWidthFlag()) value |= STATUS_INDEX_WIDTH;
|
||
|
if (!emulationFlag() && accumulatorWidthFlag()) value |= STATUS_ACCUMULATOR_WIDTH;
|
||
|
if (overflowFlag()) value |= STATUS_OVERFLOW;
|
||
|
if (signFlag()) value |= STATUS_SIGN;
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
void CpuStatus::setRegisterValue(uint8_t value) {
|
||
|
if (value & STATUS_CARRY) setCarryFlag();
|
||
|
else clearCarryFlag();
|
||
|
|
||
|
if (value & STATUS_ZERO) setZeroFlag();
|
||
|
else clearZeroFlag();
|
||
|
|
||
|
if (value & STATUS_INTERRUPT_DISABLE) setInterruptDisableFlag();
|
||
|
else clearInterruptDisableFlag();
|
||
|
|
||
|
if (value & STATUS_DECIMAL) setDecimalFlag();
|
||
|
else clearDecimalFlag();
|
||
|
|
||
|
if (emulationFlag()) {
|
||
|
if (value & STATUS_BREAK) setBreakFlag();
|
||
|
else clearBreakFlag();
|
||
|
} else {
|
||
|
if (value & STATUS_INDEX_WIDTH) setIndexWidthFlag();
|
||
|
else clearIndexWidthFlag();
|
||
|
}
|
||
|
|
||
|
if (!emulationFlag() && (value & STATUS_ACCUMULATOR_WIDTH)) setAccumulatorWidthFlag();
|
||
|
else clearAccumulatorWidthFlag();
|
||
|
|
||
|
if (value & STATUS_OVERFLOW) setOverflowFlag();
|
||
|
else clearOverflowFlag();
|
||
|
|
||
|
if (value & STATUS_SIGN) setSignFlag();
|
||
|
else clearSignFlag();
|
||
|
}
|
||
|
|
||
|
void CpuStatus::updateZeroFlagFrom8BitValue(uint8_t value) {
|
||
|
if (Binary::is8bitValueZero(value)) setZeroFlag();
|
||
|
else clearZeroFlag();
|
||
|
}
|
||
|
|
||
|
void CpuStatus::updateZeroFlagFrom16BitValue(uint16_t value) {
|
||
|
if (Binary::is16bitValueZero(value)) setZeroFlag();
|
||
|
else clearZeroFlag();
|
||
|
}
|
||
|
|
||
|
void CpuStatus::updateSignFlagFrom8BitValue(uint8_t value) {
|
||
|
if (Binary::is8bitValueNegative(value)) setSignFlag();
|
||
|
else clearSignFlag();
|
||
|
}
|
||
|
|
||
|
void CpuStatus::updateSignFlagFrom16BitValue(uint16_t value) {
|
||
|
if (Binary::is16bitValueNegative(value)) setSignFlag();
|
||
|
else clearSignFlag();
|
||
|
}
|
||
|
|
||
|
void CpuStatus::updateSignAndZeroFlagFrom8BitValue(uint8_t value) {
|
||
|
updateSignFlagFrom8BitValue(value);
|
||
|
updateZeroFlagFrom8BitValue(value);
|
||
|
}
|
||
|
|
||
|
void CpuStatus::updateSignAndZeroFlagFrom16BitValue(uint16_t value) {
|
||
|
updateSignFlagFrom16BitValue(value);
|
||
|
updateZeroFlagFrom16BitValue(value);
|
||
|
}
|