mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-02 01:31:15 +00:00
Add enough wiring to consolidate failure on lazy handling of flags.
This commit is contained in:
parent
82f0cd790f
commit
b6d000ac5e
@ -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 <typename FlowControllerT>
|
||||
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.
|
||||
|
24
InstructionSets/x86/Interrupts.hpp
Normal file
24
InstructionSets/x86/Interrupts.hpp
Normal file
@ -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 */
|
@ -1129,6 +1129,7 @@
|
||||
42437B342ACF02A9006DFED1 /* Status.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Status.hpp; sourceTree = "<group>"; };
|
||||
42437B352ACF0AA2006DFED1 /* Perform.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Perform.hpp; sourceTree = "<group>"; };
|
||||
42437B382ACF2798006DFED1 /* PerformImplementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PerformImplementation.hpp; sourceTree = "<group>"; };
|
||||
42437B392AD07465006DFED1 /* Interrupts.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Interrupts.hpp; sourceTree = "<group>"; };
|
||||
4281572E2AA0334300E16AA1 /* Carry.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Carry.hpp; sourceTree = "<group>"; };
|
||||
428168372A16C25C008ECD27 /* LineLayout.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LineLayout.hpp; sourceTree = "<group>"; };
|
||||
428168392A37AFB4008ECD27 /* DispatcherTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DispatcherTests.mm; sourceTree = "<group>"; };
|
||||
@ -5007,6 +5008,7 @@
|
||||
42437B352ACF0AA2006DFED1 /* Perform.hpp */,
|
||||
42437B342ACF02A9006DFED1 /* Status.hpp */,
|
||||
42437B372ACF2798006DFED1 /* Implementation */,
|
||||
42437B392AD07465006DFED1 /* Interrupts.hpp */,
|
||||
);
|
||||
path = x86;
|
||||
sourceTree = "<group>";
|
||||
|
@ -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<IntT *>(&memory[physical_address]);
|
||||
return access<IntT>(physical_address);
|
||||
}
|
||||
|
||||
template <typename IntT> IntT &access(uint32_t address) {
|
||||
return *reinterpret_cast<IntT *>(&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<uint16_t>(index) << 2;
|
||||
const uint16_t new_ip = memory_.access<uint16_t>(address);
|
||||
const uint16_t new_cs = memory_.access<uint16_t>(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<uint8_t>(InstructionSet::x86::Source::SS, registers_.sp_) = value >> 8;
|
||||
--registers_.sp_;
|
||||
memory_.access<uint8_t>(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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user