From bb73eb0db35f9784ba5864386ec079d93f5aca84 Mon Sep 17 00:00:00 2001
From: Thomas Harte <thomas.harte@gmail.com>
Date: Thu, 28 Apr 2022 15:35:40 -0400
Subject: [PATCH] Start working on an isolation of 68000 instruction execution.

---
 InstructionSets/M68k/Perform.hpp              | 38 +++++++++
 InstructionSets/M68k/Status.hpp               | 77 +++++++++++++++++++
 .../Clock Signal.xcodeproj/project.pbxproj    |  8 +-
 3 files changed, 121 insertions(+), 2 deletions(-)
 create mode 100644 InstructionSets/M68k/Perform.hpp
 create mode 100644 InstructionSets/M68k/Status.hpp

diff --git a/InstructionSets/M68k/Perform.hpp b/InstructionSets/M68k/Perform.hpp
new file mode 100644
index 000000000..142a08dc8
--- /dev/null
+++ b/InstructionSets/M68k/Perform.hpp
@@ -0,0 +1,38 @@
+//
+//  Perform.hpp
+//  Clock Signal
+//
+//  Created by Thomas Harte on 28/04/2022.
+//  Copyright © 2022 Thomas Harte. All rights reserved.
+//
+
+#ifndef InstructionSets_M68k_Perform_h
+#define InstructionSets_M68k_Perform_h
+
+#include "Model.hpp"
+#include "Instruction.hpp"
+#include "Status.hpp"
+#include "../../Numeric/RegisterSizes.hpp"
+
+namespace InstructionSet {
+namespace M68k {
+
+struct NullExceptionHandler {
+	void raise_exception(int)	{}
+	void consume_cycles(int)	{}
+};
+
+/// Performs @c op using @c source and @c dest (which mmay be ignored as per the semantics of the operation).
+/// And change in provcessor status will be applied to @c status. If this operation raises an exception or consumes
+/// additional cycles due to the particular value of the operands (on the 68000, think DIV or MUL), that'll be notified to
+/// @c exception_handler.
+template <
+	Operation op,
+	Model model,
+	typename ExceptionHandler
+> void perform(CPU::RegisterPair32 &source, CPU::RegisterPair32 &dest, Status &status, ExceptionHandler &exception_handler);
+
+}
+}
+
+#endif /* InstructionSets_M68k_Perform_h */
diff --git a/InstructionSets/M68k/Status.hpp b/InstructionSets/M68k/Status.hpp
new file mode 100644
index 000000000..10359239a
--- /dev/null
+++ b/InstructionSets/M68k/Status.hpp
@@ -0,0 +1,77 @@
+//
+//  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.
+
+	/* b7–b9 */
+	int interrupt_level_ = 0;			// The direct integer value of thee current interrupt level.
+
+	/* b0–b4 */
+	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_;
+	}
+};
+
+}
+}
+
+#endif /* InstructionSets_M68k_Status_h */
diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj
index b4c22e7ea..6b5d6d875 100644
--- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj	
+++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj	
@@ -1932,6 +1932,8 @@
 		4BB4BFB722A4372E0069048D /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaticAnalyser.hpp; sourceTree = "<group>"; };
 		4BB4BFB822A4372E0069048D /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = "<group>"; };
 		4BB5B995281B1D3E00522DA9 /* RegisterSizes.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = RegisterSizes.hpp; sourceTree = "<group>"; };
+		4BB5B996281B1E3F00522DA9 /* Perform.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Perform.hpp; sourceTree = "<group>"; };
+		4BB5B997281B1F7B00522DA9 /* Status.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Status.hpp; sourceTree = "<group>"; };
 		4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimedEventLoop.cpp; sourceTree = "<group>"; };
 		4BB697CA1D4B6D3E00248BDF /* TimedEventLoop.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TimedEventLoop.hpp; sourceTree = "<group>"; };
 		4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommodoreGCR.cpp; path = Encodings/CommodoreGCR.cpp; sourceTree = "<group>"; };
@@ -3157,10 +3159,12 @@
 		4B79629B2819681F008130F9 /* M68k */ = {
 			isa = PBXGroup;
 			children = (
+				4B79629F2819681F008130F9 /* Decoder.cpp */,
+				4B79629E2819681F008130F9 /* Decoder.hpp */,
 				4B79629C2819681F008130F9 /* Instruction.hpp */,
 				4B79629D2819681F008130F9 /* Model.hpp */,
-				4B79629E2819681F008130F9 /* Decoder.hpp */,
-				4B79629F2819681F008130F9 /* Decoder.cpp */,
+				4BB5B996281B1E3F00522DA9 /* Perform.hpp */,
+				4BB5B997281B1F7B00522DA9 /* Status.hpp */,
 			);
 			path = M68k;
 			sourceTree = "<group>";