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 = ""; }; 4BB4BFB822A4372E0069048D /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = ""; }; 4BB5B995281B1D3E00522DA9 /* RegisterSizes.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = RegisterSizes.hpp; sourceTree = ""; }; + 4BB5B996281B1E3F00522DA9 /* Perform.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Perform.hpp; sourceTree = ""; }; + 4BB5B997281B1F7B00522DA9 /* Status.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Status.hpp; sourceTree = ""; }; 4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimedEventLoop.cpp; sourceTree = ""; }; 4BB697CA1D4B6D3E00248BDF /* TimedEventLoop.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TimedEventLoop.hpp; sourceTree = ""; }; 4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommodoreGCR.cpp; path = Encodings/CommodoreGCR.cpp; sourceTree = ""; }; @@ -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 = "";