1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +00:00
CLK/InstructionSets/M68k/Status.hpp

105 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
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 thee 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 the condition described in the low four bits of @c code
template <typename IntT> bool evaluate_condition(IntT code) {
switch(code & 0xf) {
default:
case 0x00: return true; // true
case 0x01: return false; // false
case 0x02: return zero_result_ && !carry_flag_; // high
case 0x03: return !zero_result_ || carry_flag_; // low or same
case 0x04: return !carry_flag_; // carry clear
case 0x05: return carry_flag_; // carry set
case 0x06: return zero_result_; // not equal
case 0x07: return !zero_result_; // equal
case 0x08: return !overflow_flag_; // overflow clear
case 0x09: return overflow_flag_; // overflow set
case 0x0a: return !negative_flag_; // positive
case 0x0b: return negative_flag_; // negative
case 0x0c: // greater than or equal
return (negative_flag_ && overflow_flag_) || (!negative_flag_ && !overflow_flag_);
case 0x0d: // less than
return (negative_flag_ && !overflow_flag_) || (!negative_flag_ && overflow_flag_);
case 0x0e: // greater than
return zero_result_ && ((negative_flag_ && overflow_flag_) || (!negative_flag_ && !overflow_flag_));
case 0x0f: // less than or equal
return !zero_result_ || (negative_flag_ && !overflow_flag_) || (!negative_flag_ && overflow_flag_);
}
}
};
}
}
#endif /* InstructionSets_M68k_Status_h */