From b6d000ac5e154c234b2fe6dfe3a590c40abec3bc Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 6 Oct 2023 13:22:35 -0400 Subject: [PATCH] Add enough wiring to consolidate failure on lazy handling of flags. --- .../Implementation/PerformImplementation.hpp | 23 ++++++---- InstructionSets/x86/Interrupts.hpp | 24 ++++++++++ .../Clock Signal.xcodeproj/project.pbxproj | 2 + OSBindings/Mac/Clock SignalTests/8088Tests.mm | 46 +++++++++++++++++-- 4 files changed, 82 insertions(+), 13 deletions(-) create mode 100644 InstructionSets/x86/Interrupts.hpp diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index 6f4a8df92..a5c427c22 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -11,6 +11,7 @@ #include "../../../Numeric/Carry.hpp" #include "../../../Numeric/RegisterSizes.hpp" +#include "../Interrupts.hpp" namespace InstructionSet::x86 { @@ -108,7 +109,8 @@ inline void aad(CPU::RegisterPair16 &ax, uint8_t imm, Status &status) { status.parity = status.zero = ax.halves.low; } -inline void aam(CPU::RegisterPair16 &ax, uint8_t imm, Status &status) { +template +inline void aam(CPU::RegisterPair16 &ax, uint8_t imm, Status &status, FlowControllerT &flow_controller) { /* tempAL ← AL; AH ← tempAL / imm8; (* imm8 is set to 0AH for the AAD mnemonic *) @@ -121,12 +123,15 @@ inline void aam(CPU::RegisterPair16 &ax, uint8_t imm, Status &status) { /* If ... an immediate value of 0 is used, it will cause a #DE (divide error) exception. */ + if(!imm) { + flow_controller.interrupt(Interrupt::DivideByZero); + return; + } + ax.halves.high = ax.halves.low / imm; ax.halves.low = ax.halves.low % imm; status.sign = ax.halves.low & 0x80; status.parity = status.zero = ax.halves.low; - - // TODO: #DE. } inline void aas(CPU::RegisterPair16 &ax, Status &status) { @@ -303,13 +308,13 @@ template < default: return; //assert(false); - case Operation::AAA: Primitive::aaa(registers.axp(), status); return; - case Operation::AAD: Primitive::aad(registers.axp(), instruction.operand(), status); return; - case Operation::AAM: Primitive::aam(registers.axp(), instruction.operand(), status); return; - case Operation::AAS: Primitive::aas(registers.axp(), status); return; + case Operation::AAA: Primitive::aaa(registers.axp(), status); return; + case Operation::AAD: Primitive::aad(registers.axp(), instruction.operand(), status); return; + case Operation::AAM: Primitive::aam(registers.axp(), instruction.operand(), status, flow_controller); return; + case Operation::AAS: Primitive::aas(registers.axp(), status); return; - case Operation::ADC: Primitive::adc(destination(), source(), status); break; - case Operation::ADD: Primitive::add(destination(), source(), status); break; + case Operation::ADC: Primitive::adc(destination(), source(), status); break; + case Operation::ADD: Primitive::add(destination(), source(), status); break; } // Write to memory if required to complete this operation. diff --git a/InstructionSets/x86/Interrupts.hpp b/InstructionSets/x86/Interrupts.hpp new file mode 100644 index 000000000..0fb424999 --- /dev/null +++ b/InstructionSets/x86/Interrupts.hpp @@ -0,0 +1,24 @@ +// +// Interrupts.hpp +// Clock Signal +// +// Created by Thomas Harte on 06/10/2023. +// Copyright © 2023 Thomas Harte. All rights reserved. +// + +#ifndef InstructionSets_M68k_Interrupts_h +#define InstructionSets_M68k_Interrupts_h + +namespace InstructionSet::x86 { + +enum Interrupt { + DivideByZero = 0, + SingleStep = 1, + NMI = 2, + OneByte = 3, + OnOverflow = 4, +}; + +} + +#endif /* InstructionSets_M68k_Interrupts_h */ diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 1f67f4bdb..a7ef975c3 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -1129,6 +1129,7 @@ 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 = ""; }; + 42437B392AD07465006DFED1 /* Interrupts.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Interrupts.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 = ""; }; @@ -5007,6 +5008,7 @@ 42437B352ACF0AA2006DFED1 /* Perform.hpp */, 42437B342ACF02A9006DFED1 /* Status.hpp */, 42437B372ACF2798006DFED1 /* Implementation */, + 42437B392AD07465006DFED1 /* Interrupts.hpp */, ); path = x86; sourceTree = ""; diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index 296beca58..f080c0475 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -27,6 +27,7 @@ namespace { // provide their real path here. constexpr char TestSuiteHome[] = "/Users/tharte/Projects/ProcessorTests/8088/v1"; +using Status = InstructionSet::x86::Status; struct Registers { CPU::RegisterPair16 ax_; uint8_t &al() { return ax_.halves.low; } @@ -97,15 +98,52 @@ struct Memory { default: physical_address = registers_.ds_; break; case Source::ES: physical_address = registers_.es_; break; case Source::CS: physical_address = registers_.cs_; break; - case Source::DS: physical_address = registers_.ds_; break; + case Source::SS: physical_address = registers_.ss_; break; } physical_address = ((physical_address << 4) + address) & 0xf'ffff; - return *reinterpret_cast(&memory[physical_address]); + return access(physical_address); + } + + template IntT &access(uint32_t address) { + return *reinterpret_cast(&memory[address]); } }; struct IO { }; -struct FlowController { +class FlowController { + public: + FlowController(Memory &memory, Registers ®isters, Status &status) : + memory_(memory), registers_(registers), status_(status) {} + + void interrupt(int index) { + const uint16_t address = static_cast(index) << 2; + const uint16_t new_ip = memory_.access(address); + const uint16_t new_cs = memory_.access(address + 2); + + push(status_.get()); + + // TODO: set I and TF +// status_. + + // Push CS and IP. + push(registers_.cs_); + push(registers_.ip_); + + registers_.cs_ = new_cs; + registers_.ip_ = new_ip; + } + + private: + Memory &memory_; + Registers ®isters_; + Status status_; + + void push(uint16_t value) { + --registers_.sp_; + memory_.access(InstructionSet::x86::Source::SS, registers_.sp_) = value >> 8; + --registers_.sp_; + memory_.access(InstructionSet::x86::Source::SS, registers_.sp_) = value & 0xff; + } }; } @@ -275,9 +313,9 @@ struct FlowController { const auto decoded = decoder.decode(data.data(), data.size()); InstructionSet::x86::Status status; - FlowController flow_controller; Registers registers; Memory memory(registers); + FlowController flow_controller(memory, registers, status); IO io; // Apply initial state.