diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp new file mode 100644 index 000000000..34dedab8a --- /dev/null +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -0,0 +1,110 @@ +// +// PerformImplementation.hpp +// Clock Signal +// +// Created by Thomas Harte on 05/10/2023. +// Copyright © 2023 Thomas Harte. All rights reserved. +// + +#ifndef PerformImplementation_h +#define PerformImplementation_h + +namespace InstructionSet::x86 { + +namespace Primitive { + +void aaa(CPU::RegisterPair16 &ax, Status &status) { + /* + IF ((AL AND 0FH) > 9) OR (AF = 1) + THEN + AL ← (AL + 6); + AH ← AH + 1; + AF ← 1; + CF ← 1; + ELSE + AF ← 0; + CF ← 0; + FI; + AL ← AL AND 0FH; + */ + /* + The AF and CF flags are set to 1 if the adjustment results in a decimal carry; + otherwise they are cleared to 0. The OF, SF, ZF, and PF flags are undefined. + */ + if((ax.halves.low & 0x0f) > 9 || status.auxiliary_carry) { + ax.halves.low += 6; + ++ax.halves.high; + status.auxiliary_carry = status.carry = 1; + } else { + status.auxiliary_carry = status.carry = 0; + } +} + +void aad(CPU::RegisterPair16 &ax, uint8_t imm, Status &status) { + /* + tempAL ← AL; + tempAH ← AH; + AL ← (tempAL + (tempAH * imm8)) AND FFH; (* imm8 is set to 0AH for the AAD mnemonic *) + AH ← 0 + */ + /* + The SF, ZF, and PF flags are set according to the result; + the OF, AF, and CF flags are undefined. + */ + ax.halves.low = ax.halves.low + (ax.halves.high * imm); + ax.halves.high = 0; + status.sign = ax.halves.low & 0x80; + status.parity = status.zero = ax.halves.low; +} + +} + +template < + Model model, + Operation operation, + DataSize data_size, + typename FlowControllerT +> void perform( + CPU::RegisterPair16 &destination, + CPU::RegisterPair16 &source, + Status &status, + FlowControllerT &flow_controller +) { + switch(operation) { + case Operation::AAA: Primitive::aaa(destination, status); break; + case Operation::AAD: Primitive::aad(destination, source.halves.low, status); break; + } + + (void)flow_controller; +} + + +/*template < + Model model, + typename InstructionT, + typename FlowControllerT, + typename DataPointerResolverT, + typename RegistersT, + typename MemoryT, + typename IOT, + Operation operation +> void perform( + const InstructionT &instruction, + Status &status, + FlowControllerT &flow_controller, + DataPointerResolverT &resolver, + RegistersT ®isters, + MemoryT &memory, + IOT &io +) { + switch((operation != Operation::Invalid) ? operation : instruction.operation) { + default: + assert(false); + return; + } +}*/ + + +} + +#endif /* PerformImplementation_h */ diff --git a/InstructionSets/x86/Perform.hpp b/InstructionSets/x86/Perform.hpp index fe84da795..048894827 100644 --- a/InstructionSets/x86/Perform.hpp +++ b/InstructionSets/x86/Perform.hpp @@ -10,6 +10,9 @@ #define Perform_h #include "Instruction.hpp" +#include "Model.hpp" +#include "Status.hpp" +#include "../../Numeric/RegisterSizes.hpp" namespace InstructionSet::x86 { @@ -22,14 +25,15 @@ namespace InstructionSet::x86 { /// whatever is specifed in @c instruction. template < Model model, + typename InstructionT, typename FlowControllerT, typename DataPointerResolverT, typename RegistersT, typename MemoryT, typename IOT, - Operation operation = Operation::Undefined + Operation operation = Operation::Invalid > void perform( - const Instruction &instruction, + const InstructionT &instruction, Status &status, FlowControllerT &flow_controller, DataPointerResolverT &resolver, @@ -38,6 +42,32 @@ template < IOT &io ); +template < + Model model, + Operation operation, + DataSize data_size, + typename FlowControllerT +> void perform( + CPU::RegisterPair32 &destination, + CPU::RegisterPair32 &source, + Status &status, + FlowControllerT &flow_controller +); + +template < + Model model, + Operation operation, + DataSize data_size, + typename FlowControllerT +> void perform( + CPU::RegisterPair16 &destination, + CPU::RegisterPair16 &source, + Status &status, + FlowControllerT &flow_controller +); + } +#include "Implementation/PerformImplementation.hpp" + #endif /* Perform_h */ diff --git a/InstructionSets/x86/Status.hpp b/InstructionSets/x86/Status.hpp index 8ccb31c6b..4c922ca6b 100644 --- a/InstructionSets/x86/Status.hpp +++ b/InstructionSets/x86/Status.hpp @@ -54,6 +54,16 @@ static constexpr uint32_t VirtualMode = 1 << 17; } struct Status { + // Non-zero => set; zero => unset. + uint32_t carry; + uint32_t auxiliary_carry; + uint32_t sign; + + // Zero => set; non-zero => unset. + uint32_t zero; + + // Odd number of bits => set; even => unset. + uint32_t parity; }; } diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index a285bc85d..1f67f4bdb 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -1128,6 +1128,7 @@ 423BDC492AB24699008E37B6 /* 8088Tests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = 8088Tests.mm; sourceTree = ""; }; 42437B342ACF02A9006DFED1 /* Status.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Status.hpp; sourceTree = ""; }; 42437B352ACF0AA2006DFED1 /* Perform.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Perform.hpp; sourceTree = ""; }; + 42437B382ACF2798006DFED1 /* PerformImplementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PerformImplementation.hpp; sourceTree = ""; }; 4281572E2AA0334300E16AA1 /* Carry.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Carry.hpp; sourceTree = ""; }; 428168372A16C25C008ECD27 /* LineLayout.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LineLayout.hpp; sourceTree = ""; }; 428168392A37AFB4008ECD27 /* DispatcherTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DispatcherTests.mm; sourceTree = ""; }; @@ -2325,6 +2326,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 42437B372ACF2798006DFED1 /* Implementation */ = { + isa = PBXGroup; + children = ( + 42437B382ACF2798006DFED1 /* PerformImplementation.hpp */, + ); + path = Implementation; + sourceTree = ""; + }; 42A5E8322ABBE16F00A0DD5D /* Neskell Tests */ = { isa = PBXGroup; children = ( @@ -4995,8 +5004,9 @@ 4BEDA3B825B25563000C2DBD /* Decoder.hpp */, 4BEDA3DB25B2588F000C2DBD /* Instruction.hpp */, 4BE3C69527CBC540000EAD28 /* Model.hpp */, - 42437B342ACF02A9006DFED1 /* Status.hpp */, 42437B352ACF0AA2006DFED1 /* Perform.hpp */, + 42437B342ACF02A9006DFED1 /* Status.hpp */, + 42437B372ACF2798006DFED1 /* Implementation */, ); path = x86; sourceTree = ""; diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index a7f81b22f..ce5fa332a 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -18,6 +18,7 @@ #include "NSData+dataWithContentsOfGZippedFile.h" #include "../../../InstructionSets/x86/Decoder.hpp" +#include "../../../InstructionSets/x86/Perform.hpp" namespace { @@ -185,4 +186,26 @@ constexpr char TestSuiteHome[] = "/Users/tharte/Projects/ProcessorTests/8088/v1" NSLog(@"%ld failures out of %ld tests: %@", failures.count, testFiles.count, [[failures allObjects] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]); } +- (void)testExecution { + CPU::RegisterPair16 source, dest; + InstructionSet::x86::Status status; + struct NoFlow { + } flow_controller; + + dest.full = 0xff; + source.full = 10; + + InstructionSet::x86::perform< + InstructionSet::x86::Model::i8086, + InstructionSet::x86::Operation::AAD, + InstructionSet::x86::DataSize::Byte + >( + dest, + source, + status, + flow_controller + ); + +} + @end