1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-19 08:31:11 +00:00
CLK/InstructionSets/M68k/Status.hpp

122 lines
3.7 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 {
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.
/* b7b9 */
int interrupt_level = 0; // The direct integer value of the current interrupt level.
/* b0b4 */
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 */