1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-07 23:29:06 +00:00
CLK/InstructionSets/M68k/Status.hpp
2022-05-01 13:00:20 -04:00

107 lines
3.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Status.hpp
// Clock Signal
//
// Created by Thomas Harte on 28/04/2022.
// Copyright © 2022 Thomas Harte. All rights reserved.
//
#ifndef InstructionSets_M68k_Status_h
#define InstructionSets_M68k_Status_h
#include "Instruction.hpp"
namespace InstructionSet {
namespace M68k {
struct Status {
/* b15 */
uint_fast32_t trace_flag_ = 0; // The trace flag is set if this value is non-zero.
/* b13 */
int is_supervisor_ = 0; // 1 => processor is in supervisor mode; 0 => it isn't.
/* b7b9 */
int interrupt_level_ = 0; // The direct integer value of the current interrupt level.
/* b0b4 */
uint_fast32_t zero_result_ = 0; // The zero flag is set if this value is zero.
uint_fast32_t carry_flag_ = 0; // The carry flag is set if this value is non-zero.
uint_fast32_t extend_flag_ = 0; // The extend flag is set if this value is non-zero.
uint_fast32_t overflow_flag_ = 0; // The overflow flag is set if this value is non-zero.
uint_fast32_t negative_flag_ = 0; // The negative flag is set if this value is non-zero.
/// Gets the current condition codes.
constexpr uint16_t ccr() const {
return
(carry_flag_ ? 0x0001 : 0x0000) |
(overflow_flag_ ? 0x0002 : 0x0000) |
(zero_result_ ? 0x0000 : 0x0004) |
(negative_flag_ ? 0x0008 : 0x0000) |
(extend_flag_ ? 0x0010 : 0x0000);
}
/// Gets the current value of the status register.
constexpr uint16_t status() const {
return uint16_t(
ccr() |
(interrupt_level_ << 8) |
(trace_flag_ ? 0x8000 : 0x0000) |
(is_supervisor_ << 13)
);
}
/// Sets the current condition codes.
constexpr void set_ccr(uint16_t ccr) {
carry_flag_ = (ccr) & 0x0001;
overflow_flag_ = (ccr) & 0x0002;
zero_result_ = ((ccr) & 0x0004) ^ 0x0004;
negative_flag_ = (ccr) & 0x0008;
extend_flag_ = (ccr) & 0x0010;
}
/// Sets the current value of the status register;
/// @returns @c true if the processor finishes in supervisor mode; @c false otherwise.
constexpr bool set_status(uint16_t status) {
set_ccr(status);
interrupt_level_ = (status >> 8) & 7;
trace_flag_ = status & 0x8000;
is_supervisor_ = (status >> 13) & 1;
return is_supervisor_;
}
/// Evaluates @c condition.
bool evaluate_condition(Condition condition) {
switch(condition) {
default:
case Condition::True: return true;
case Condition::False: return false;
case Condition::High: return zero_result_ && !carry_flag_;
case Condition::LowOrSame: return !zero_result_ || carry_flag_;
case Condition::CarryClear: return !carry_flag_;
case Condition::CarrySet: return carry_flag_;
case Condition::NotEqual: return zero_result_;
case Condition::Equal: return !zero_result_;
case Condition::OverflowClear: return !overflow_flag_;
case Condition::OverflowSet: return overflow_flag_;
case Condition::Positive: return !negative_flag_;
case Condition::Negative: return negative_flag_;
case Condition::GreaterThanOrEqual:
return (negative_flag_ && overflow_flag_) || (!negative_flag_ && !overflow_flag_);
case Condition::LessThan:
return (negative_flag_ && !overflow_flag_) || (!negative_flag_ && overflow_flag_);
case Condition::GreaterThan:
return zero_result_ && ((negative_flag_ && overflow_flag_) || (!negative_flag_ && !overflow_flag_));
case Condition::LessThanOrEqual:
return !zero_result_ || (negative_flag_ && !overflow_flag_) || (!negative_flag_ && overflow_flag_);
}
}
};
}
}
#endif /* InstructionSets_M68k_Status_h */