1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-17 02:30:54 +00:00

Bifurcate the fetch-operand flow.

Address calculation will be the same, but the fetch will differ. I don't think there's a neat costless way to factor out the address calculations, alas, but I'll see whether macros can save the day.
This commit is contained in:
Thomas Harte 2022-05-19 10:27:51 -04:00
parent 29f6b02c04
commit c6c6213460
6 changed files with 62 additions and 41 deletions

View File

@ -12,8 +12,9 @@
namespace InstructionSet {
namespace M68k {
constexpr DataSize operand_size(Operation operation) {
switch(operation) {
template <Operation t_operation>
constexpr DataSize operand_size(Operation r_operation) {
switch((t_operation == Operation::Undefined) ? r_operation : t_operation) {
// These are given a value arbitrarily, to
// complete the switch statement.
case Operation::Undefined:

View File

@ -135,7 +135,8 @@ enum class DataSize {
/// For any operations that don't fit the neat model of reading one or two operands,
/// then writing zero or one, the size determines the data size of the operands only,
/// not any other accesses.
constexpr DataSize operand_size(Operation operation);
template <Operation t_operation = Operation::Undefined>
constexpr DataSize operand_size(Operation operation = Operation::Undefined);
template <Operation t_op = Operation::Undefined>
constexpr uint32_t quick(uint16_t instruction, Operation r_op = Operation::Undefined) {

View File

@ -16,7 +16,7 @@
{ "name" : "PEA 0007", "initial state": {"pc": 256, "sr": 9994, "d0": 1936773744, "a0": 80356190, "d1": 1946694636, "a1": 1926755014, "d2": 1183385206, "a2": 1065607184, "d3": 1309119182, "a3": 1793825962, "d4": 1396128358, "a4": 310023100, "d5": 1323002590, "a5": 762930884, "d6": 658865898, "a6": 2102011604, "d7": 1133480560, "a7": 63167722, "usp": 921123988}, "final state": {"pc": 258, "sr": 9992, "d0": 1936773744, "a0": 80356190, "d1": 1946694636, "a1": 1926755014, "d2": 1183385206, "a2": 1065607184, "d3": 1309119182, "a3": 1793825962, "d4": 1396128358, "a4": 310023100, "d5": 1323002590, "a5": 762930884, "d6": 658865898, "a6": 2102011604, "d7": 2322613135, "a7": 63167722, "usp": 921123988}, "initial memory": [0, 3, 1, 195, 2, 220, 3, 234, 4, 0, 5, 0, 6, 1, 7, 0, 256, 72, 257, 71, 258, 104, 259, 224, 260, 40, 261, 76, 262, 8, 263, 204, 264, 160, 265, 134, -1], "final memory": [-1]},
{"initial memory":[0,249,1,29,2,33,3,130,4,0,5,0,6,1,7,0,256,72,257,16,258,112,259,38,260,160,261,118,262,152,263,30,264,168,265,4,6744600,64,-1],"final memory":[-1],"final state":{"d3":2035604306,"a6":1464166520,"a1":1603474990,"a2":831870726,"d4":839607392,"a7":4179435906,"d0":618692302,"a3":1132766718,"d5":166392906,"usp":921123988,"d1":245717746,"a4":967715578,"d6":541879554,"sr":10003,"a0":224848408,"d2":167120648,"d7":2039017604,"pc":258,"a5":1502060714},"name":"NBCD 0010","initial state":{"d3":2035604306,"a6":1464166520,"d7":2039017604,"a2":831870726,"d4":839607392,"a7":4179435906,"d0":618692302,"a3":1132766718,"d5":166392906,"usp":921123988,"d1":245717746,"a4":967715578,"d6":541879554,"sr":9985,"a0":224848408,"d2":167120648,"pc":256,"a5":1502060714,"a1":1603474990}},
{ "name" : "PEA 0010", "initial state": {"pc": 256, "sr": 10011, "d0": 1979469332, "a0": 636868838, "d1": 124420406, "a1": 796063618, "d2": 1632191918, "a2": 618106916, "d3": 293459048, "a3": 1144536672, "d4": 1543766224, "a4": 1216836932, "d5": 181503714, "a5": 891545742, "d6": 1106142458, "a6": 1215897482, "d7": 170359526, "a7": 1050022966, "usp": 921123988}, "final state": {"pc": 258, "sr": 10011, "d0": 1979469332, "a0": 636868838, "d1": 124420406, "a1": 796063618, "d2": 1632191918, "a2": 618106916, "d3": 293459048, "a3": 1144536672, "d4": 1543766224, "a4": 1216836932, "d5": 181503714, "a5": 891545742, "d6": 1106142458, "a6": 1215897482, "d7": 170359526, "a7": 1050022962, "usp": 921123988}, "initial memory": [0, 62, 1, 150, 2, 20, 3, 54, 4, 0, 5, 0, 6, 1, 7, 0, 256, 72, 257, 80, 258, 72, 259, 170, 260, 8, 261, 24, 262, 40, 263, 26, 264, 136, 265, 66, -1], "final memory": [9835570, 37, 9835571, 245, 9835572, 216, 9835573, 230, -1]},
"initial memory":[0,134,1,119,2,3,3,116,4,0,5,0,6,1,7,0,256,72,257,17,258,56,259,142,260,248,261,170,262,192,263,76,264,8,265,222,2151716,40,-1],"final memory":[-1],"final state":{"d3":295850370,"a6":1119147342,"a1":622908708,"a2":243876230,"d4":932525784,"a7":2255946612,"d0":776721210,"a3":1429015940,"d5":625212688,"usp":921123988,"d1":1947770004,"a4":13812338,"d6":312179252,"sr":10003,"a0":670590652,"d2":2077226006,"d7":494138742,"pc":258,"a5":215747696},"name":"NBCD 0011","initial state":{"d3":295850370,"a6":1119147342,"d7":494138742,"a2":243876230,"d4":932525784,"a7":2255946612,"d0":776721210,"a3":1429015940,"d5":625212688,"usp":921123988,"d1":1947770004,"a4":13812338,"d6":312179252,"sr":10005,"a0":670590652,"d2":2077226006,"pc":256,"a5":215747696,"a1":622908708}},
{"initial memory":[0,134,1,119,2,3,3,116,4,0,5,0,6,1,7,0,256,72,257,17,258,56,259,142,260,248,261,170,262,192,263,76,264,8,265,222,2151716,40,-1],"final memory":[-1],"final state":{"d3":295850370,"a6":1119147342,"a1":622908708,"a2":243876230,"d4":932525784,"a7":2255946612,"d0":776721210,"a3":1429015940,"d5":625212688,"usp":921123988,"d1":1947770004,"a4":13812338,"d6":312179252,"sr":10003,"a0":670590652,"d2":2077226006,"d7":494138742,"pc":258,"a5":215747696},"name":"NBCD 0011","initial state":{"d3":295850370,"a6":1119147342,"d7":494138742,"a2":243876230,"d4":932525784,"a7":2255946612,"d0":776721210,"a3":1429015940,"d5":625212688,"usp":921123988,"d1":1947770004,"a4":13812338,"d6":312179252,"sr":10005,"a0":670590652,"d2":2077226006,"pc":256,"a5":215747696,"a1":622908708}},
{ "name" : "PEA 0011", "initial state": {"pc": 256, "sr": 10015, "d0": 1525896150, "a0": 1114700052, "d1": 486897382, "a1": 116437536, "d2": 1371621010, "a2": 608065134, "d3": 1744864978, "a3": 2023531518, "d4": 2056502268, "a4": 1943205940, "d5": 2031803458, "a5": 530946810, "d6": 1383247658, "a6": 828499192, "d7": 1732926038, "a7": 1860960810, "usp": 921123988}, "final state": {"pc": 258, "sr": 10015, "d0": 1525896150, "a0": 1114700052, "d1": 486897382, "a1": 116437536, "d2": 1371621010, "a2": 608065134, "d3": 1744864978, "a3": 2023531518, "d4": 2056502268, "a4": 1943205940, "d5": 2031803458, "a5": 530946810, "d6": 1383247658, "a6": 828499192, "d7": 1732926038, "a7": 1860960806, "usp": 921123988}, "initial memory": [0, 110, 1, 236, 2, 2, 3, 42, 4, 0, 5, 0, 6, 1, 7, 0, 256, 72, 257, 81, 258, 248, 259, 150, 260, 96, 261, 142, 262, 184, 263, 216, 264, 32, 265, 212, -1], "final memory": [15467046, 6, 15467047, 240, 15467048, 178, 15467049, 32, -1]},
{ "name" : "NBCD 0012", "initial state": {"pc": 256, "sr": 9997, "d0": 710108312, "a0": 1826616548, "d1": 1223790212, "a1": 1665588370, "d2": 1791205764, "a2": 1094412752, "d3": 1369528708, "a3": 597686308, "d4": 939283616, "a4": 1532778344, "d5": 387461822, "a5": 191798196, "d6": 900424650, "a6": 179326024, "d7": 119832140, "a7": 3940930444, "usp": 921123988}, "final state": {"pc": 258, "sr": 10009, "d0": 710108312, "a0": 1826616548, "d1": 1223790212, "a1": 1665588370, "d2": 1791205764, "a2": 1094412752, "d3": 1369528708, "a3": 597686308, "d4": 939283616, "a4": 1532778344, "d5": 387461822, "a5": 191798196, "d6": 900424650, "a6": 179326024, "d7": 119832140, "a7": 3940930444, "usp": 921123988}, "initial memory": [0, 234, 1, 229, 2, 211, 3, 140, 4, 0, 5, 0, 6, 1, 7, 0, 256, 72, 257, 18, 258, 64, 259, 146, 260, 240, 261, 218, 262, 184, 263, 104, 264, 224, 265, 64, 3893712, 252, -1], "final memory": [-1]},
{ "name" : "PEA 0012", "initial state": {"pc": 256, "sr": 10006, "d0": 693352294, "a0": 1624162156, "d1": 925736636, "a1": 628718874, "d2": 336618736, "a2": 1258588884, "d3": 1079186560, "a3": 389467244, "d4": 241648164, "a4": 245830658, "d5": 489132678, "a5": 2064832632, "d6": 285518430, "a6": 306310504, "d7": 1229785612, "a7": 3992919702, "usp": 921123988}, "final state": {"pc": 258, "sr": 10006, "d0": 693352294, "a0": 1624162156, "d1": 925736636, "a1": 628718874, "d2": 336618736, "a2": 1258588884, "d3": 1079186560, "a3": 389467244, "d4": 241648164, "a4": 245830658, "d5": 489132678, "a5": 2064832632, "d6": 285518430, "a6": 306310504, "d7": 1229785612, "a7": 3992919698, "usp": 921123988}, "initial memory": [0, 237, 1, 255, 2, 30, 3, 150, 4, 0, 5, 0, 6, 1, 7, 0, 256, 72, 257, 82, 258, 192, 259, 30, 260, 128, 261, 152, 262, 0, 263, 88, 264, 104, 265, 122, -1], "final memory": [16719506, 75, 16719507, 4, 16719508, 138, 16719509, 212, -1]},

View File

@ -155,7 +155,7 @@ struct TestProcessor: public CPU::MC68000Mk2::BusHandler {
#endif
// To limit tests run to a subset of files and/or of tests, uncomment and fill in below.
// _fileSet = [NSSet setWithArray:@[@"exg.json"]];
_fileSet = [NSSet setWithArray:@[@"nbcd_pea.json"]];
// _testSet = [NSSet setWithArray:@[@"CHK 41a8"]];
}

View File

@ -22,7 +22,12 @@ enum ExecutionState: int {
Reset = std::numeric_limits<int>::min(),
Decode,
WaitForDTACK,
FetchOperand,
/// Perform the proper sequence to fetch a byte or word operand.
FetchOperandbw,
/// Perform the proper sequence to fetch a long-word operand.
FetchOperandl,
StoreOperand,
// Specific addressing mode fetches.
@ -139,8 +144,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
// Performs the memory access implied by the announce, perform pair,
// honouring DTACK, BERR and VPA as necessary.
#define AccessPair(addr, val, announce, perform) \
announce.address = perform.address = &addr; \
#define AccessPair(val, announce, perform) \
perform.value = &val; \
if constexpr (!dtack_is_implicit) { \
announce.length = HalfCycles(4); \
@ -149,13 +153,19 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
WaitForDTACK(announce); \
CompleteAccess(perform);
// Reads the data (i.e. non-program) word from addr into val.
#define ReadDataWord(addr, val) \
AccessPair(addr, val, read_word_data_announce, read_word_data)
// Sets up the next data access — its address and size/read flags.
#define SetupDataAccess(addr, read_flag, select_flag) \
access.address = access_announce.address = &addr; \
access_announce.operation = Microcycle::NewAddress | Microcycle::IsData | read_flag; \
access.operation = access_announce.operation | select_flag;
// Performs the access established by SetupDataAccess into val.
#define Access(val) \
AccessPair(val, access_announce, access)
// Reads the program (i.e. non-data) word from addr into val.
#define ReadProgramWord(val) \
AccessPair(program_counter_.l, val, read_program_announce, read_program); \
#define ReadProgramWord(val) \
AccessPair(val, read_program_announce, read_program); \
program_counter_.l += 2;
// Reads one futher word from the program counter and inserts it into
@ -192,17 +202,19 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
status_.trace_flag = 0;
did_update_status();
SetupDataAccess(temporary_address_, Microcycle::Read, Microcycle::SelectWord);
temporary_address_ = 0;
ReadDataWord(temporary_address_, registers_[15].high); // nF
Access(registers_[15].high); // nF
temporary_address_ += 2;
ReadDataWord(temporary_address_, registers_[15].low); // nf
Access(registers_[15].low); // nf
temporary_address_ += 2;
ReadDataWord(temporary_address_, program_counter_.high); // nV
Access(program_counter_.high); // nV
temporary_address_ += 2;
ReadDataWord(temporary_address_, program_counter_.low); // nv
Access(program_counter_.low); // nv
Prefetch(); // np
IdleBus(1); // n
@ -233,6 +245,19 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
case InstructionSet::M68k::Operation::x: \
operand_flags_ = InstructionSet::M68k::operand_flags<InstructionSet::M68k::Model::M68000, InstructionSet::M68k::Operation::x>();
#define FetchOperands(x) \
if constexpr (InstructionSet::M68k::operand_size<InstructionSet::M68k::Operation::x>() == InstructionSet::M68k::DataSize::LongWord) { \
SetupDataAccess(temporary_address_, Microcycle::Read, Microcycle::SelectWord); \
MoveToState(FetchOperandl); \
} else { \
if constexpr (InstructionSet::M68k::operand_size<InstructionSet::M68k::Operation::x>() == InstructionSet::M68k::DataSize::Byte) { \
SetupDataAccess(temporary_address_, Microcycle::Read, Microcycle::SelectByte); \
} else { \
SetupDataAccess(temporary_address_, Microcycle::Read, Microcycle::SelectWord); \
} \
MoveToState(FetchOperandbw); \
}
switch(instruction_.operation) {
CASE(NBCD)
if(instruction_.mode(0) == Mode::DataRegisterDirect) {
@ -240,31 +265,34 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
} else {
perform_state_ = Perform_np;
}
break;
FetchOperands(NBCD)
CASE(SWAP)
perform_state_ = Perform_np;
FetchOperands(SWAP)
CASE(MOVEw)
perform_state_ = MOVEw;
break;
FetchOperands(MOVEw)
default:
assert(false);
}
#undef CASE
[[fallthrough]];
#define MoveToNextOperand() \
#define MoveToNextOperand(x) \
++next_operand_; \
if(next_operand_ == 2) { \
state_ = perform_state_; \
continue; \
} \
MoveToState(FetchOperand)
MoveToState(x)
// Check the operand flags to determine whether the operand at index
// operand_ needs to be fetched, and if so then calculate the EA and
// do so.
BeginState(FetchOperand):
BeginState(FetchOperandbw):
// Check that this operand is meant to be fetched; if not then either:
//
// (i) this operand isn't used; or
@ -280,11 +308,11 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
case Mode::AddressRegisterDirect:
case Mode::DataRegisterDirect:
operand_[next_operand_] = registers_[instruction_.lreg(next_operand_)];
MoveToNextOperand();
MoveToNextOperand(FetchOperandbw);
case Mode::Quick:
operand_[next_operand_].l = InstructionSet::M68k::quick(opcode_, instruction_.operation);
MoveToNextOperand();
MoveToNextOperand(FetchOperandbw);
case Mode::AddressRegisterIndirect:
MoveToState(FetchAddressRegisterIndirect);
@ -391,6 +419,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
TODOState(FetchAbsoluteShort);
TODOState(FetchAbsoluteLong);
TODOState(FetchImmediateData);
TODOState(FetchOperandl);
#undef TODOState

View File

@ -19,6 +19,10 @@ namespace CPU {
namespace MC68000Mk2 {
struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
ProcessorBase() {
read_program_announce.address = read_program.address = &program_counter_.l;
}
int state_ = std::numeric_limits<int>::min();
/// Counts time left on the clock before the current batch of processing
@ -123,26 +127,12 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
};
// Read a data word or byte.
Microcycle read_word_data_announce {
Microcycle access_announce {
Microcycle::Read | Microcycle::NewAddress | Microcycle::IsData
};
Microcycle read_word_data {
Microcycle access {
Microcycle::Read | Microcycle::SameAddress | Microcycle::SelectWord | Microcycle::IsData
};
Microcycle read_byte_data {
Microcycle::Read | Microcycle::SameAddress | Microcycle::SelectByte | Microcycle::IsData
};
// Write a data word or byte.
Microcycle write_word_data_announce {
Microcycle::NewAddress | Microcycle::IsData
};
Microcycle write_word_data {
Microcycle::SameAddress | Microcycle::SelectWord | Microcycle::IsData
};
Microcycle write_byte_data {
Microcycle::SameAddress | Microcycle::SelectByte | Microcycle::IsData
};
// Holding spot when awaiting DTACK/etc.
Microcycle awaiting_dtack;