mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-16 18:30:32 +00:00
Merge pull request #1342 from TomHarte/ARM2Status
Add some degree of ARM 2 status flags.
This commit is contained in:
commit
cd21b39f44
134
InstructionSets/ARM/Status.hpp
Normal file
134
InstructionSets/ARM/Status.hpp
Normal file
@ -0,0 +1,134 @@
|
||||
//
|
||||
// Status.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 25/02/2024.
|
||||
// Copyright © 2024 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "OperationMapper.hpp"
|
||||
|
||||
namespace InstructionSet::ARM {
|
||||
|
||||
namespace ConditionCode {
|
||||
|
||||
static constexpr uint32_t Negative = 1 << 31;
|
||||
static constexpr uint32_t Zero = 1 << 30;
|
||||
static constexpr uint32_t Carry = 1 << 29;
|
||||
static constexpr uint32_t Overflow = 1 << 28;
|
||||
static constexpr uint32_t IRQDisable = 1 << 27;
|
||||
static constexpr uint32_t FIQDisable = 1 << 26;
|
||||
static constexpr uint32_t Mode = (1 << 1) | (1 << 0);
|
||||
|
||||
static constexpr uint32_t Address = FIQDisable - Mode - 1;
|
||||
|
||||
}
|
||||
|
||||
enum class Mode {
|
||||
User = 0b00,
|
||||
FIQ = 0b01,
|
||||
IRQ = 0b10,
|
||||
Supervisor = 0b11,
|
||||
};
|
||||
|
||||
struct Status {
|
||||
public:
|
||||
/// Sets the N and Z flags according to the value of @c result.
|
||||
void set_nz(uint32_t value) {
|
||||
zero_result_ = negative_flag_ = value;
|
||||
}
|
||||
|
||||
/// Sets C if @c value is non-zero; resets it otherwise.
|
||||
void set_c(uint32_t value) {
|
||||
carry_flag_ = value;
|
||||
}
|
||||
|
||||
/// Sets V if the highest bit of @c value is set; resets it otherwise.
|
||||
void set_v(uint32_t value) {
|
||||
overflow_flag_ = value;
|
||||
}
|
||||
|
||||
/// @returns The program counter address only, optionally with a post-increment.
|
||||
template <bool increment>
|
||||
uint32_t pc() {
|
||||
const uint32_t result = pc_;
|
||||
if constexpr (increment) {
|
||||
pc_ = (pc_ + 4) & ConditionCode::Address;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void begin_irq() { interrupt_flags_ |= ConditionCode::IRQDisable; }
|
||||
void begin_fiq() { interrupt_flags_ |= ConditionCode::FIQDisable; }
|
||||
|
||||
/// @returns The full PC + status bits.
|
||||
uint32_t get() const {
|
||||
return
|
||||
uint32_t(mode_) |
|
||||
pc_ |
|
||||
(negative_flag_ & ConditionCode::Negative) |
|
||||
(zero_result_ ? 0 : ConditionCode::Zero) |
|
||||
(carry_flag_ ? ConditionCode::Carry : 0) |
|
||||
((overflow_flag_ >> 3) & ConditionCode::Overflow) |
|
||||
interrupt_flags_;
|
||||
}
|
||||
|
||||
bool test(Condition condition) {
|
||||
const auto ne = [&]() -> bool {
|
||||
return zero_result_;
|
||||
};
|
||||
const auto cs = [&]() -> bool {
|
||||
return carry_flag_;
|
||||
};
|
||||
const auto mi = [&]() -> bool {
|
||||
return negative_flag_ & ConditionCode::Negative;
|
||||
};
|
||||
const auto vs = [&]() -> bool {
|
||||
return overflow_flag_ & ConditionCode::Negative;
|
||||
};
|
||||
const auto hi = [&]() -> bool {
|
||||
return carry_flag_ && zero_result_;
|
||||
};
|
||||
const auto lt = [&]() -> bool {
|
||||
return (negative_flag_ ^ overflow_flag_) & ConditionCode::Negative;
|
||||
};
|
||||
const auto le = [&]() -> bool {
|
||||
return !zero_result_ || lt();
|
||||
};
|
||||
|
||||
switch(condition) {
|
||||
case Condition::EQ: return !ne();
|
||||
case Condition::NE: return ne();
|
||||
case Condition::CS: return cs();
|
||||
case Condition::CC: return !cs();
|
||||
case Condition::MI: return mi();
|
||||
case Condition::PL: return !mi();
|
||||
case Condition::VS: return vs();
|
||||
case Condition::VC: return !vs();
|
||||
|
||||
case Condition::HI: return hi();
|
||||
case Condition::LS: return !hi();
|
||||
case Condition::GE: return !lt();
|
||||
case Condition::LT: return lt();
|
||||
case Condition::GT: return !le();
|
||||
case Condition::LE: return le();
|
||||
|
||||
case Condition::AL: return true;
|
||||
case Condition::NV: return false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t pc_ = 0;
|
||||
Mode mode_ = Mode::Supervisor;
|
||||
|
||||
uint32_t zero_result_ = 0;
|
||||
uint32_t negative_flag_ = 0;
|
||||
uint32_t interrupt_flags_ = 0;
|
||||
uint32_t carry_flag_ = 0;
|
||||
uint32_t overflow_flag_ = 0;
|
||||
};
|
||||
|
||||
}
|
@ -1335,6 +1335,7 @@
|
||||
4B1EDB431E39A0AC009D6819 /* chip.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = chip.png; sourceTree = "<group>"; };
|
||||
4B2005402B804AA300420C5C /* OperationMapper.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = OperationMapper.hpp; sourceTree = "<group>"; };
|
||||
4B2005422B804D6400420C5C /* ARMDecoderTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ARMDecoderTests.mm; sourceTree = "<group>"; };
|
||||
4B2005462B8BD7A500420C5C /* Status.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Status.hpp; sourceTree = "<group>"; };
|
||||
4B2130E0273A7A0A008A77B4 /* Audio.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Audio.cpp; sourceTree = "<group>"; };
|
||||
4B2130E1273A7A0A008A77B4 /* Audio.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Audio.hpp; sourceTree = "<group>"; };
|
||||
4B228CD424D773B30077EF25 /* CSScanTarget.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CSScanTarget.mm; sourceTree = "<group>"; };
|
||||
@ -2759,6 +2760,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B2005402B804AA300420C5C /* OperationMapper.hpp */,
|
||||
4B2005462B8BD7A500420C5C /* Status.hpp */,
|
||||
);
|
||||
path = ARM;
|
||||
sourceTree = "<group>";
|
||||
|
@ -9,6 +9,7 @@
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#include "../../../InstructionSets/ARM/OperationMapper.hpp"
|
||||
#include "../../../InstructionSets/ARM/Status.hpp"
|
||||
|
||||
using namespace InstructionSet::ARM;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user