diff --git a/InstructionSets/ARM/Status.hpp b/InstructionSets/ARM/Status.hpp
new file mode 100644
index 000000000..3cf3cba60
--- /dev/null
+++ b/InstructionSets/ARM/Status.hpp
@@ -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;
+};
+
+}
diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj
index 5534d4fbe..b7ea5cdac 100644
--- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj	
+++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj	
@@ -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>";
diff --git a/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm b/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm
index 3cfeffbce..5e5533b2b 100644
--- a/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm	
+++ b/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm	
@@ -9,6 +9,7 @@
 #import <XCTest/XCTest.h>
 
 #include "../../../InstructionSets/ARM/OperationMapper.hpp"
+#include "../../../InstructionSets/ARM/Status.hpp"
 
 using namespace InstructionSet::ARM;