mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Consume operand_flags into Instruction.hpp.
This commit is contained in:
parent
c61809f0c4
commit
b3cf13775b
@ -13,7 +13,6 @@
|
||||
#include "Instruction.hpp"
|
||||
#include "Model.hpp"
|
||||
#include "Perform.hpp"
|
||||
#include "Sequence.hpp"
|
||||
#include "Status.hpp"
|
||||
|
||||
namespace InstructionSet {
|
||||
|
@ -108,7 +108,7 @@ typename Executor<model, BusHandler>::EffectiveAddress Executor<model, BusHandle
|
||||
ea.requires_fetch = false;
|
||||
break;
|
||||
case AddressingMode::Quick:
|
||||
ea.value.l = quick(instruction.operation, opcode);
|
||||
ea.value.l = quick(opcode, instruction.operation);
|
||||
ea.requires_fetch = false;
|
||||
break;
|
||||
case AddressingMode::ImmediateData:
|
||||
|
@ -9,9 +9,11 @@
|
||||
#ifndef InstructionSets_68k_Instruction_hpp
|
||||
#define InstructionSets_68k_Instruction_hpp
|
||||
|
||||
#include <cstdint>
|
||||
#include "Model.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
namespace InstructionSet {
|
||||
namespace M68k {
|
||||
|
||||
@ -224,9 +226,9 @@ constexpr DataSize size(Operation operation) {
|
||||
}
|
||||
}
|
||||
|
||||
template <Operation op>
|
||||
constexpr uint32_t quick(uint16_t instruction) {
|
||||
switch(op) {
|
||||
template <Operation t_op = Operation::Undefined>
|
||||
constexpr uint32_t quick(uint16_t instruction, Operation r_op = Operation::Undefined) {
|
||||
switch((t_op != Operation::Undefined) ? t_op : r_op) {
|
||||
case Operation::Bccb:
|
||||
case Operation::BSRb:
|
||||
case Operation::MOVEl: return uint32_t(int8_t(instruction));
|
||||
@ -239,16 +241,85 @@ constexpr uint32_t quick(uint16_t instruction) {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr uint32_t quick(Operation op, uint16_t instruction) {
|
||||
switch(op) {
|
||||
case Operation::MOVEl: return quick<Operation::MOVEl>(instruction);
|
||||
case Operation::Bccb: return quick<Operation::Bccb>(instruction);
|
||||
case Operation::BSRb: return quick<Operation::BSRb>(instruction);
|
||||
case Operation::TRAP: return quick<Operation::TRAP>(instruction);
|
||||
static constexpr uint8_t FetchOp1 = (1 << 0);
|
||||
static constexpr uint8_t FetchOp2 = (1 << 1);
|
||||
static constexpr uint8_t StoreOp1 = (1 << 2);
|
||||
static constexpr uint8_t StoreOp2 = (1 << 3);
|
||||
|
||||
/*!
|
||||
Provides a bitfield with a value in the range 0–15 indicating which of the provided operation's
|
||||
operands are accessed via standard fetch and store cycles.
|
||||
|
||||
Unusual bus sequences, such as TAS or MOVEM, are not described here.
|
||||
*/
|
||||
template <Model model, Operation t_operation = Operation::Undefined> uint8_t operand_flags(Operation r_operation = Operation::Undefined) {
|
||||
switch((t_operation != Operation::Undefined) ? t_operation : r_operation) {
|
||||
default:
|
||||
// ADDw is arbitrary; anything other than those listed above will do.
|
||||
return quick<Operation::ADDw>(instruction);
|
||||
assert(false);
|
||||
|
||||
//
|
||||
// No operands are fetched or stored.
|
||||
//
|
||||
case Operation::LEA:
|
||||
case Operation::PEA:
|
||||
return 0;
|
||||
|
||||
//
|
||||
// Single-operand read.
|
||||
//
|
||||
case Operation::MOVEtoSR: case Operation::MOVEtoCCR: case Operation::MOVEtoUSP:
|
||||
case Operation::ORItoSR: case Operation::ORItoCCR:
|
||||
case Operation::ANDItoSR: case Operation::ANDItoCCR:
|
||||
case Operation::EORItoSR: case Operation::EORItoCCR:
|
||||
return FetchOp1;
|
||||
|
||||
//
|
||||
// Single-operand write.
|
||||
//
|
||||
case Operation::MOVEfromSR: case Operation::MOVEfromUSP:
|
||||
return StoreOp1;
|
||||
|
||||
//
|
||||
// Single-operand read-modify-write.
|
||||
//
|
||||
case Operation::NBCD:
|
||||
case Operation::EXTbtow: case Operation::EXTwtol:
|
||||
return FetchOp1 | StoreOp1;
|
||||
|
||||
//
|
||||
// Two-operand; read both.
|
||||
//
|
||||
case Operation::CMPb: case Operation::CMPw: case Operation::CMPl:
|
||||
case Operation::CMPAw: case Operation::CMPAl:
|
||||
return FetchOp1 | FetchOp2;
|
||||
|
||||
//
|
||||
// Two-operand; read source, write dest.
|
||||
//
|
||||
case Operation::MOVEb: case Operation::MOVEw: case Operation::MOVEl:
|
||||
case Operation::MOVEAw: case Operation::MOVEAl:
|
||||
return FetchOp1 | StoreOp2;
|
||||
|
||||
//
|
||||
// Two-operand; read both, write dest.
|
||||
//
|
||||
case Operation::ABCD: case Operation::SBCD:
|
||||
case Operation::ADDb: case Operation::ADDw: case Operation::ADDl:
|
||||
case Operation::ADDAw: case Operation::ADDAl:
|
||||
case Operation::ADDXb: case Operation::ADDXw: case Operation::ADDXl:
|
||||
case Operation::SUBb: case Operation::SUBw: case Operation::SUBl:
|
||||
case Operation::SUBAw: case Operation::SUBAl:
|
||||
case Operation::SUBXb: case Operation::SUBXw: case Operation::SUBXl:
|
||||
case Operation::ORb: case Operation::ORw: case Operation::ORl:
|
||||
case Operation::ANDb: case Operation::ANDw: case Operation::ANDl:
|
||||
case Operation::EORb: case Operation::EORw: case Operation::EORl:
|
||||
return FetchOp1 | FetchOp2 | StoreOp2;
|
||||
|
||||
//
|
||||
// Two-operand; read both, write both.
|
||||
//
|
||||
case Operation::EXG:
|
||||
return FetchOp1 | FetchOp2 | StoreOp1 | StoreOp2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,114 +0,0 @@
|
||||
//
|
||||
// Sequence.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 29/04/2022.
|
||||
// Copyright © 2022 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Sequence.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
using namespace InstructionSet::M68k;
|
||||
|
||||
/*
|
||||
template <Step... T> struct Steps {
|
||||
static constexpr uint32_t value = 0;
|
||||
};
|
||||
|
||||
template <Step F, Step... T> struct Steps<F, T...> {
|
||||
static constexpr uint32_t value = uint16_t(F) | uint16_t(Steps<T...>::value << 4);
|
||||
};
|
||||
|
||||
template<Model model> uint32_t Sequence<model>::steps_for(Operation operation) {
|
||||
switch(operation) {
|
||||
// This handles a NOP, and not much else.
|
||||
default: assert(false);
|
||||
|
||||
//
|
||||
// No operands that require fetching.
|
||||
//
|
||||
case Operation::LEA:
|
||||
return Steps<
|
||||
Step::Perform
|
||||
>::value;
|
||||
|
||||
//
|
||||
// No logic, custom bus activity required.
|
||||
//
|
||||
case Operation::PEA:
|
||||
return Steps<
|
||||
Step::SpecificBusActivity
|
||||
>::value;
|
||||
|
||||
//
|
||||
// Single operand, read.
|
||||
//
|
||||
case Operation::MOVEtoSR: case Operation::MOVEtoCCR: case Operation::MOVEtoUSP:
|
||||
case Operation::ORItoSR: case Operation::ORItoCCR:
|
||||
case Operation::ANDItoSR: case Operation::ANDItoCCR:
|
||||
case Operation::EORItoSR: case Operation::EORItoCCR:
|
||||
return Steps<
|
||||
Step::FetchOp1,
|
||||
Step::Perform
|
||||
>::value;
|
||||
|
||||
//
|
||||
// Single operand, write.
|
||||
//
|
||||
case Operation::MOVEfromSR: case Operation::MOVEfromUSP:
|
||||
return Steps<
|
||||
Step::Perform,
|
||||
Step::StoreOp1
|
||||
>::value;
|
||||
|
||||
//
|
||||
// Single operand, read-modify-write.
|
||||
//
|
||||
case Operation::NBCD:
|
||||
case Operation::EXTbtow: case Operation::EXTwtol:
|
||||
return Steps<
|
||||
Step::FetchOp1,
|
||||
Step::Perform,
|
||||
Step::StoreOp1
|
||||
>::value;
|
||||
|
||||
//
|
||||
// Two operand, read-write.
|
||||
//
|
||||
case Operation::MOVEb: case Operation::MOVEw: case Operation::MOVEl:
|
||||
case Operation::MOVEAw: case Operation::MOVEAl:
|
||||
return Steps<
|
||||
Step::FetchOp1,
|
||||
Step::Perform,
|
||||
Step::StoreOp2
|
||||
>::value;
|
||||
|
||||
//
|
||||
// Two operand, read-modify-write.
|
||||
//
|
||||
case Operation::ABCD: case Operation::SBCD:
|
||||
case Operation::ADDb: case Operation::ADDw: case Operation::ADDl:
|
||||
case Operation::ADDAw: case Operation::ADDAl:
|
||||
case Operation::ADDXb: case Operation::ADDXw: case Operation::ADDXl:
|
||||
case Operation::SUBb: case Operation::SUBw: case Operation::SUBl:
|
||||
case Operation::SUBAw: case Operation::SUBAl:
|
||||
case Operation::SUBXb: case Operation::SUBXw: case Operation::SUBXl:
|
||||
return Steps<
|
||||
Step::FetchOp1,
|
||||
Step::FetchOp2,
|
||||
Step::Perform,
|
||||
Step::StoreOp2
|
||||
>::value;
|
||||
}
|
||||
}
|
||||
|
||||
template<Model model> Sequence<model>::Sequence(Operation operation) : steps_(steps_for(operation)) {}
|
||||
|
||||
template class InstructionSet::M68k::Sequence<Model::M68000>;
|
||||
template class InstructionSet::M68k::Sequence<Model::M68010>;
|
||||
template class InstructionSet::M68k::Sequence<Model::M68020>;
|
||||
template class InstructionSet::M68k::Sequence<Model::M68030>;
|
||||
template class InstructionSet::M68k::Sequence<Model::M68040>;
|
||||
*/
|
@ -1,106 +0,0 @@
|
||||
//
|
||||
// Sequencer.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 29/04/2022.
|
||||
// Copyright © 2022 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef InstructionSets_68k_Sequencer_hpp
|
||||
#define InstructionSets_68k_Sequencer_hpp
|
||||
|
||||
#include "Instruction.hpp"
|
||||
#include "Model.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace InstructionSet {
|
||||
namespace M68k {
|
||||
|
||||
static constexpr uint8_t FetchOp1 = (1 << 0);
|
||||
static constexpr uint8_t FetchOp2 = (1 << 1);
|
||||
static constexpr uint8_t StoreOp1 = (1 << 2);
|
||||
static constexpr uint8_t StoreOp2 = (1 << 3);
|
||||
|
||||
/*!
|
||||
Provides a bitfield with a value in the range 0–15 indicating which of the provided operation's
|
||||
operands are accessed via standard fetch and store cycles.
|
||||
|
||||
Unusual bus sequences, such as TAS or MOVEM, are not described here.
|
||||
*/
|
||||
template <Model model, Operation t_operation = Operation::Undefined> uint8_t operand_flags(Operation r_operation = Operation::Undefined) {
|
||||
switch((t_operation != Operation::Undefined) ? t_operation : r_operation) {
|
||||
default:
|
||||
assert(false);
|
||||
|
||||
//
|
||||
// No operands are fetched or stored.
|
||||
//
|
||||
case Operation::LEA:
|
||||
case Operation::PEA:
|
||||
return 0;
|
||||
|
||||
//
|
||||
// Single-operand read.
|
||||
//
|
||||
case Operation::MOVEtoSR: case Operation::MOVEtoCCR: case Operation::MOVEtoUSP:
|
||||
case Operation::ORItoSR: case Operation::ORItoCCR:
|
||||
case Operation::ANDItoSR: case Operation::ANDItoCCR:
|
||||
case Operation::EORItoSR: case Operation::EORItoCCR:
|
||||
return FetchOp1;
|
||||
|
||||
//
|
||||
// Single-operand write.
|
||||
//
|
||||
case Operation::MOVEfromSR: case Operation::MOVEfromUSP:
|
||||
return StoreOp1;
|
||||
|
||||
//
|
||||
// Single-operand read-modify-write.
|
||||
//
|
||||
case Operation::NBCD:
|
||||
case Operation::EXTbtow: case Operation::EXTwtol:
|
||||
return FetchOp1 | StoreOp1;
|
||||
|
||||
//
|
||||
// Two-operand; read both.
|
||||
//
|
||||
case Operation::CMPb: case Operation::CMPw: case Operation::CMPl:
|
||||
case Operation::CMPAw: case Operation::CMPAl:
|
||||
return FetchOp1 | FetchOp2;
|
||||
|
||||
//
|
||||
// Two-operand; read source, write dest.
|
||||
//
|
||||
case Operation::MOVEb: case Operation::MOVEw: case Operation::MOVEl:
|
||||
case Operation::MOVEAw: case Operation::MOVEAl:
|
||||
return FetchOp1 | StoreOp2;
|
||||
|
||||
//
|
||||
// Two-operand; read both, write dest.
|
||||
//
|
||||
case Operation::ABCD: case Operation::SBCD:
|
||||
case Operation::ADDb: case Operation::ADDw: case Operation::ADDl:
|
||||
case Operation::ADDAw: case Operation::ADDAl:
|
||||
case Operation::ADDXb: case Operation::ADDXw: case Operation::ADDXl:
|
||||
case Operation::SUBb: case Operation::SUBw: case Operation::SUBl:
|
||||
case Operation::SUBAw: case Operation::SUBAl:
|
||||
case Operation::SUBXb: case Operation::SUBXw: case Operation::SUBXl:
|
||||
case Operation::ORb: case Operation::ORw: case Operation::ORl:
|
||||
case Operation::ANDb: case Operation::ANDw: case Operation::ANDl:
|
||||
case Operation::EORb: case Operation::EORw: case Operation::EORl:
|
||||
return FetchOp1 | FetchOp2 | StoreOp2;
|
||||
|
||||
//
|
||||
// Two-operand; read both, write both.
|
||||
//
|
||||
case Operation::EXG:
|
||||
return FetchOp1 | FetchOp2 | StoreOp1 | StoreOp2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* InstructionSets_68k_Sequencer_h */
|
@ -427,8 +427,6 @@
|
||||
4B7962A02819681F008130F9 /* Decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B79629F2819681F008130F9 /* Decoder.cpp */; };
|
||||
4B7962A12819681F008130F9 /* Decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B79629F2819681F008130F9 /* Decoder.cpp */; };
|
||||
4B7962A22819681F008130F9 /* Decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B79629F2819681F008130F9 /* Decoder.cpp */; };
|
||||
4B7962A5281C32D8008130F9 /* Sequence.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7962A4281C2EE3008130F9 /* Sequence.cpp */; };
|
||||
4B7962A6281C32D8008130F9 /* Sequence.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7962A4281C2EE3008130F9 /* Sequence.cpp */; };
|
||||
4B79A5011FC913C900EEDAD5 /* MSX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B79A4FF1FC913C900EEDAD5 /* MSX.cpp */; };
|
||||
4B79E4441E3AF38600141F11 /* cassette.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B79E4411E3AF38600141F11 /* cassette.png */; };
|
||||
4B79E4451E3AF38600141F11 /* floppy35.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B79E4421E3AF38600141F11 /* floppy35.png */; };
|
||||
@ -1427,8 +1425,6 @@
|
||||
4B79629D2819681F008130F9 /* Model.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Model.hpp; sourceTree = "<group>"; };
|
||||
4B79629E2819681F008130F9 /* Decoder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Decoder.hpp; sourceTree = "<group>"; };
|
||||
4B79629F2819681F008130F9 /* Decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Decoder.cpp; sourceTree = "<group>"; };
|
||||
4B7962A3281C1B76008130F9 /* Sequence.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Sequence.hpp; sourceTree = "<group>"; };
|
||||
4B7962A4281C2EE3008130F9 /* Sequence.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Sequence.cpp; sourceTree = "<group>"; };
|
||||
4B79A4FE1FC9082300EEDAD5 /* TypedDynamicMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TypedDynamicMachine.hpp; sourceTree = "<group>"; };
|
||||
4B79A4FF1FC913C900EEDAD5 /* MSX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MSX.cpp; sourceTree = "<group>"; };
|
||||
4B79A5001FC913C900EEDAD5 /* MSX.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MSX.hpp; sourceTree = "<group>"; };
|
||||
@ -3167,13 +3163,11 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B79629F2819681F008130F9 /* Decoder.cpp */,
|
||||
4B7962A4281C2EE3008130F9 /* Sequence.cpp */,
|
||||
4B79629E2819681F008130F9 /* Decoder.hpp */,
|
||||
4BB5B99C281C805300522DA9 /* Executor.hpp */,
|
||||
4B79629C2819681F008130F9 /* Instruction.hpp */,
|
||||
4B79629D2819681F008130F9 /* Model.hpp */,
|
||||
4BB5B996281B1E3F00522DA9 /* Perform.hpp */,
|
||||
4B7962A3281C1B76008130F9 /* Sequence.hpp */,
|
||||
4BB5B997281B1F7B00522DA9 /* Status.hpp */,
|
||||
4BB5B999281B244400522DA9 /* Implementation */,
|
||||
);
|
||||
@ -5470,7 +5464,6 @@
|
||||
4BC080CB26A238CC00D03FD8 /* AmigaADF.cpp in Sources */,
|
||||
4B4B1A3D200198CA00A0F866 /* KonamiSCC.cpp in Sources */,
|
||||
4B055AC31FAE9AE80060FFFF /* AmstradCPC.cpp in Sources */,
|
||||
4B7962A5281C32D8008130F9 /* Sequence.cpp in Sources */,
|
||||
4B055A9E1FAE85DA0060FFFF /* G64.cpp in Sources */,
|
||||
4B055AB81FAE860F0060FFFF /* ZX80O81P.cpp in Sources */,
|
||||
4B055AB01FAE86070060FFFF /* PulseQueuedTape.cpp in Sources */,
|
||||
@ -5707,7 +5700,6 @@
|
||||
4B894518201967B4007DE474 /* ConfidenceCounter.cpp in Sources */,
|
||||
4BCE005A227CFFCA000CA200 /* Macintosh.cpp in Sources */,
|
||||
4B6AAEA4230E3E1D0078E864 /* MassStorageDevice.cpp in Sources */,
|
||||
4B7962A6281C32D8008130F9 /* Sequence.cpp in Sources */,
|
||||
4B89452E201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||
4BC890D3230F86020025A55A /* DirectAccessDevice.cpp in Sources */,
|
||||
4B7BA03723CEB86000B98D9E /* BD500.cpp in Sources */,
|
||||
|
@ -7,9 +7,9 @@
|
||||
buildImplicitDependencies = "YES">
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
buildConfiguration = "Release"
|
||||
selectedDebuggerIdentifier = ""
|
||||
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
#define USE_EXISTING_IMPLEMENTATION
|
||||
|
||||
@interface M68000ComparativeTests : XCTestCase
|
||||
@end
|
||||
|
||||
@ -73,7 +75,11 @@
|
||||
// Perform each dictionary in the array as a test.
|
||||
for(NSDictionary *test in jsonContents) {
|
||||
if(![test isKindOfClass:[NSDictionary class]]) continue;
|
||||
#ifdef USE_EXISTING_IMPLEMENTATION
|
||||
[self testOperationClassic:test];
|
||||
#else
|
||||
[self testOperationExecutor:test];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ template <int index> NSString *operand(Preinstruction instruction, uint16_t opco
|
||||
return @"#";
|
||||
|
||||
case AddressingMode::Quick:
|
||||
return [NSString stringWithFormat:@"%d", quick(instruction.operation, opcode)];
|
||||
return [NSString stringWithFormat:@"%d", quick(opcode, instruction.operation)];
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user