mirror of
https://github.com/TomHarte/CLK.git
synced 2024-08-17 07:29:04 +00:00
122 lines
3.7 KiB
C++
122 lines
3.7 KiB
C++
//
|
||
// 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 {
|
||
using FlagT = uint_fast32_t;
|
||
|
||
enum ConditionCode: uint16_t {
|
||
Carry = (1 << 0),
|
||
Overflow = (1 << 1),
|
||
Zero = (1 << 2),
|
||
Negative = (1 << 3),
|
||
Extend = (1 << 4),
|
||
|
||
Supervisor = (1 << 13),
|
||
Trace = (1 << 15),
|
||
|
||
InterruptPriorityMask = (0b111 << 8),
|
||
};
|
||
|
||
/* b15 */
|
||
FlagT 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.
|
||
|
||
/* b7–b9 */
|
||
int interrupt_level = 0; // The direct integer value of the current interrupt level.
|
||
|
||
/* b0–b4 */
|
||
FlagT zero_result = 0; // The zero flag is set if this value is zero.
|
||
FlagT carry_flag = 0; // The carry flag is set if this value is non-zero.
|
||
FlagT extend_flag = 0; // The extend flag is set if this value is non-zero.
|
||
FlagT overflow_flag = 0; // The overflow flag is set if this value is non-zero.
|
||
FlagT 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 ? ConditionCode::Carry : 0) |
|
||
(overflow_flag ? ConditionCode::Overflow : 0) |
|
||
(zero_result ? 0 : ConditionCode::Zero) |
|
||
(negative_flag ? ConditionCode::Negative : 0) |
|
||
(extend_flag ? ConditionCode::Extend : 0);
|
||
}
|
||
|
||
/// Sets the current condition codes.
|
||
constexpr void set_ccr(uint16_t ccr) {
|
||
carry_flag = ccr & ConditionCode::Carry;
|
||
overflow_flag = ccr & ConditionCode::Overflow;
|
||
zero_result = ~ccr & ConditionCode::Zero;
|
||
negative_flag = ccr & ConditionCode::Negative;
|
||
extend_flag = ccr & ConditionCode::Extend;
|
||
}
|
||
|
||
/// Gets the current value of the status register.
|
||
constexpr uint16_t status() const {
|
||
return uint16_t(
|
||
ccr() |
|
||
(interrupt_level << 8) |
|
||
(trace_flag ? ConditionCode::Trace : 0) |
|
||
(is_supervisor << 13)
|
||
);
|
||
}
|
||
|
||
/// 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 & ConditionCode::Trace;
|
||
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 */
|