1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-17 21:30:14 +00:00

Improve commentary; use specialised types for TAS.

This commit is contained in:
Thomas Harte 2023-12-22 10:46:10 -05:00
parent 5b43ea82f3
commit c266639a0c
3 changed files with 26 additions and 27 deletions

View File

@ -35,7 +35,8 @@ static constexpr OperationT SelectWord = 1 << 1;
/// If set, indicates a read. Otherwise, a write.
static constexpr OperationT Read = 1 << 2;
// Two-bit gap deliberately left here for PermitRead/Write below.
// Two-bit gap deliberately left here for PermitRead/Write below; these are not
// real 68000 signals, they're to do with internal manipulation only.
/// A NewAddress cycle is one in which the address strobe is initially low but becomes high;
/// this correlates to states 0 to 5 of a standard read/write cycle.
@ -65,9 +66,7 @@ static constexpr OperationT IsPeripheral = 1 << 11;
/// Provides the 68000's bus grant line — indicating whether a bus request has been acknowledged.
static constexpr OperationT BusGrant = 1 << 12;
/// An otherwise invalid combination; used as the operaiton template parameter to @c perform_bus_operation if
/// the operation wasn't knowable in advance and the receiver should decode dynamically using the microcycle's
/// .operation field.
/// An otherwise invalid combination; used as an implementation detail elsewhere. Shouldn't be exposed.
static constexpr OperationT DecodeDynamically = NewAddress | SameAddress;
// PermitRead and PermitWrite are used as part of the read/write mask
@ -339,7 +338,7 @@ struct Microcycle: public MicrocycleOperationStorage<op> {
/*!
Assuming this to be a cycle with a data select active, applies it to @c target
subject to the read_write_mask, where 'applies' means:
subject to the @c read_write_mask, where 'applies' means:
* if this is a byte read, reads a single byte from @c target;
* if this is a word read, reads a word (in the host platform's endianness) from @c target; and
@ -348,7 +347,10 @@ struct Microcycle: public MicrocycleOperationStorage<op> {
forceinline void apply(uint8_t *target, OperationT read_write_mask = Operation::PermitRead | Operation::PermitWrite) const {
assert( (this->operation & (Operation::SelectWord | Operation::SelectByte)) != (Operation::SelectWord | Operation::SelectByte));
switch((this->operation | read_write_mask) & (Operation::SelectWord | Operation::SelectByte | Operation::Read | Operation::PermitRead | Operation::PermitWrite)) {
switch(
(this->operation | read_write_mask) &
(Operation::SelectWord | Operation::SelectByte | Operation::Read | Operation::PermitRead | Operation::PermitWrite)
) {
default:
break;
@ -382,11 +384,10 @@ class BusHandler {
Provides the bus handler with a single Microcycle to 'perform'.
FC0 and FC1 are provided inside the microcycle as the IsData and IsProgram
flags; FC2 is provided here as is_supervisor it'll be either 0 or 1.
flags; FC2 is provided here as @c is_supervisor it'll be either 0 or 1.
If @c operation is any value other than Microcycle::DecodeDynamically then it
can be used to select an appropriate execution path at compile time. Otherwise
cycle.operation must be inspected at runtime.
The @c Microcycle might be any instantiation of @c Microcycle above;
whether with a static constexpr operation or with a runtime-selected one.
*/
template <typename Microcycle>
HalfCycles perform_bus_operation(const Microcycle &, [[maybe_unused]] int is_supervisor) {

View File

@ -2625,20 +2625,20 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
//
BeginState(TAS):
// Populate all addresses.
tas_cycles[0].address = tas_cycles[1].address =
tas_cycles[2].address =
tas_cycles[3].address = tas_cycles[4].address = &effective_address_[0].l;
tas_cycle0.address = tas_cycle1.address =
tas_cycle2.address =
tas_cycle3.address = tas_cycle4.address = &effective_address_[0].l;
// Populate values to the relevant subset.
tas_cycles[0].value = tas_cycles[1].value =
tas_cycles[3].value = tas_cycles[4].value = &operand_[0].low;
tas_cycle0.value = tas_cycle1.value =
tas_cycle3.value = tas_cycle4.value = &operand_[0].low;
// First two parts: the read.
PerformBusOperation(tas_cycles[0]);
CompleteAccess(tas_cycles[1]);
PerformBusOperation(tas_cycle0);
CompleteAccess(tas_cycle1);
// Third part: processing time.
PerformBusOperation(tas_cycles[2]);
PerformBusOperation(tas_cycle2);
// Do the actual TAS operation.
status_.overflow_flag = status_.carry_flag = 0;
@ -2647,8 +2647,8 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
// Final parts: write back.
operand_[0].b |= 0x80;
PerformBusOperation(tas_cycles[3]);
CompleteAccess(tas_cycles[4]);
PerformBusOperation(tas_cycle3);
CompleteAccess(tas_cycle4);
Prefetch();
MoveToStateSpecific(Decode);

View File

@ -208,13 +208,11 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
Operation::SameAddress | Operation::IsData,
Operation::SameAddress | Operation::IsData | Operation::SelectByte,
};
Microcycle<Operation::DecodeDynamically> tas_cycles[5] = {
{ TASOperations[0] },
{ TASOperations[1] },
{ TASOperations[2] },
{ TASOperations[3] },
{ TASOperations[4] },
};
Microcycle<TASOperations[0]> tas_cycle0;
Microcycle<TASOperations[1]> tas_cycle1;
Microcycle<TASOperations[2]> tas_cycle2;
Microcycle<TASOperations[3]> tas_cycle3;
Microcycle<TASOperations[4]> tas_cycle4;
// Reset.
static constexpr OperationT ResetOperation = CPU::MC68000::Operation::Reset;