mirror of
https://github.com/TomHarte/CLK.git
synced 2024-07-30 23:29:08 +00:00
Add AddressRegisterIndirect fetches.
This commit is contained in:
parent
c6c6213460
commit
f46e7c65c5
@ -24,24 +24,35 @@ enum ExecutionState: int {
|
|||||||
WaitForDTACK,
|
WaitForDTACK,
|
||||||
|
|
||||||
/// Perform the proper sequence to fetch a byte or word operand.
|
/// Perform the proper sequence to fetch a byte or word operand.
|
||||||
FetchOperandbw,
|
FetchOperand_bw,
|
||||||
/// Perform the proper sequence to fetch a long-word operand.
|
/// Perform the proper sequence to fetch a long-word operand.
|
||||||
FetchOperandl,
|
FetchOperand_l,
|
||||||
|
|
||||||
StoreOperand,
|
StoreOperand,
|
||||||
|
|
||||||
// Specific addressing mode fetches.
|
// Specific addressing mode fetches.
|
||||||
|
|
||||||
FetchAddressRegisterIndirect,
|
FetchAddressRegisterIndirect_bw,
|
||||||
FetchAddressRegisterIndirectWithPostincrement,
|
FetchAddressRegisterIndirectWithPostincrement_bw,
|
||||||
FetchAddressRegisterIndirectWithPredecrement,
|
FetchAddressRegisterIndirectWithPredecrement_bw,
|
||||||
FetchAddressRegisterIndirectWithDisplacement,
|
FetchAddressRegisterIndirectWithDisplacement_bw,
|
||||||
FetchAddressRegisterIndirectWithIndex8bitDisplacement,
|
FetchAddressRegisterIndirectWithIndex8bitDisplacement_bw,
|
||||||
FetchProgramCounterIndirectWithDisplacement,
|
FetchProgramCounterIndirectWithDisplacement_bw,
|
||||||
FetchProgramCounterIndirectWithIndex8bitDisplacement,
|
FetchProgramCounterIndirectWithIndex8bitDisplacement_bw,
|
||||||
FetchAbsoluteShort,
|
FetchAbsoluteShort_bw,
|
||||||
FetchAbsoluteLong,
|
FetchAbsoluteLong_bw,
|
||||||
FetchImmediateData,
|
FetchImmediateData_bw,
|
||||||
|
|
||||||
|
FetchAddressRegisterIndirect_l,
|
||||||
|
FetchAddressRegisterIndirectWithPostincrement_l,
|
||||||
|
FetchAddressRegisterIndirectWithPredecrement_l,
|
||||||
|
FetchAddressRegisterIndirectWithDisplacement_l,
|
||||||
|
FetchAddressRegisterIndirectWithIndex8bitDisplacement_l,
|
||||||
|
FetchProgramCounterIndirectWithDisplacement_l,
|
||||||
|
FetchProgramCounterIndirectWithIndex8bitDisplacement_l,
|
||||||
|
FetchAbsoluteShort_l,
|
||||||
|
FetchAbsoluteLong_l,
|
||||||
|
FetchImmediateData_l,
|
||||||
|
|
||||||
// Various forms of perform; each of these will
|
// Various forms of perform; each of these will
|
||||||
// perform the current instruction, then do the
|
// perform the current instruction, then do the
|
||||||
@ -248,14 +259,14 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
#define FetchOperands(x) \
|
#define FetchOperands(x) \
|
||||||
if constexpr (InstructionSet::M68k::operand_size<InstructionSet::M68k::Operation::x>() == InstructionSet::M68k::DataSize::LongWord) { \
|
if constexpr (InstructionSet::M68k::operand_size<InstructionSet::M68k::Operation::x>() == InstructionSet::M68k::DataSize::LongWord) { \
|
||||||
SetupDataAccess(temporary_address_, Microcycle::Read, Microcycle::SelectWord); \
|
SetupDataAccess(temporary_address_, Microcycle::Read, Microcycle::SelectWord); \
|
||||||
MoveToState(FetchOperandl); \
|
MoveToState(FetchOperand_l); \
|
||||||
} else { \
|
} else { \
|
||||||
if constexpr (InstructionSet::M68k::operand_size<InstructionSet::M68k::Operation::x>() == InstructionSet::M68k::DataSize::Byte) { \
|
if constexpr (InstructionSet::M68k::operand_size<InstructionSet::M68k::Operation::x>() == InstructionSet::M68k::DataSize::Byte) { \
|
||||||
SetupDataAccess(temporary_address_, Microcycle::Read, Microcycle::SelectByte); \
|
SetupDataAccess(temporary_address_, Microcycle::Read, Microcycle::SelectByte); \
|
||||||
} else { \
|
} else { \
|
||||||
SetupDataAccess(temporary_address_, Microcycle::Read, Microcycle::SelectWord); \
|
SetupDataAccess(temporary_address_, Microcycle::Read, Microcycle::SelectWord); \
|
||||||
} \
|
} \
|
||||||
MoveToState(FetchOperandbw); \
|
MoveToState(FetchOperand_bw); \
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(instruction_.operation) {
|
switch(instruction_.operation) {
|
||||||
@ -281,6 +292,8 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
|
|
||||||
#undef CASE
|
#undef CASE
|
||||||
|
|
||||||
|
// MARK: - Fetch, dispatch.
|
||||||
|
|
||||||
#define MoveToNextOperand(x) \
|
#define MoveToNextOperand(x) \
|
||||||
++next_operand_; \
|
++next_operand_; \
|
||||||
if(next_operand_ == 2) { \
|
if(next_operand_ == 2) { \
|
||||||
@ -289,10 +302,10 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
} \
|
} \
|
||||||
MoveToState(x)
|
MoveToState(x)
|
||||||
|
|
||||||
// Check the operand flags to determine whether the operand at index
|
// Check the operand flags to determine whether the byte or word
|
||||||
// operand_ needs to be fetched, and if so then calculate the EA and
|
// operand at index next_operand_ needs to be fetched, and if so
|
||||||
// do so.
|
// then calculate the EA and do so.
|
||||||
BeginState(FetchOperandbw):
|
BeginState(FetchOperand_bw):
|
||||||
// Check that this operand is meant to be fetched; if not then either:
|
// Check that this operand is meant to be fetched; if not then either:
|
||||||
//
|
//
|
||||||
// (i) this operand isn't used; or
|
// (i) this operand isn't used; or
|
||||||
@ -308,32 +321,32 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
case Mode::AddressRegisterDirect:
|
case Mode::AddressRegisterDirect:
|
||||||
case Mode::DataRegisterDirect:
|
case Mode::DataRegisterDirect:
|
||||||
operand_[next_operand_] = registers_[instruction_.lreg(next_operand_)];
|
operand_[next_operand_] = registers_[instruction_.lreg(next_operand_)];
|
||||||
MoveToNextOperand(FetchOperandbw);
|
MoveToNextOperand(FetchOperand_bw);
|
||||||
|
|
||||||
case Mode::Quick:
|
case Mode::Quick:
|
||||||
operand_[next_operand_].l = InstructionSet::M68k::quick(opcode_, instruction_.operation);
|
operand_[next_operand_].l = InstructionSet::M68k::quick(opcode_, instruction_.operation);
|
||||||
MoveToNextOperand(FetchOperandbw);
|
MoveToNextOperand(FetchOperand_bw);
|
||||||
|
|
||||||
case Mode::AddressRegisterIndirect:
|
case Mode::AddressRegisterIndirect:
|
||||||
MoveToState(FetchAddressRegisterIndirect);
|
MoveToState(FetchAddressRegisterIndirect_bw);
|
||||||
case Mode::AddressRegisterIndirectWithPostincrement:
|
case Mode::AddressRegisterIndirectWithPostincrement:
|
||||||
MoveToState(FetchAddressRegisterIndirectWithPostincrement);
|
MoveToState(FetchAddressRegisterIndirectWithPostincrement_bw);
|
||||||
case Mode::AddressRegisterIndirectWithPredecrement:
|
case Mode::AddressRegisterIndirectWithPredecrement:
|
||||||
MoveToState(FetchAddressRegisterIndirectWithPredecrement);
|
MoveToState(FetchAddressRegisterIndirectWithPredecrement_bw);
|
||||||
case Mode::AddressRegisterIndirectWithDisplacement:
|
case Mode::AddressRegisterIndirectWithDisplacement:
|
||||||
MoveToState(FetchAddressRegisterIndirectWithDisplacement);
|
MoveToState(FetchAddressRegisterIndirectWithDisplacement_bw);
|
||||||
case Mode::AddressRegisterIndirectWithIndex8bitDisplacement:
|
case Mode::AddressRegisterIndirectWithIndex8bitDisplacement:
|
||||||
MoveToState(FetchAddressRegisterIndirectWithIndex8bitDisplacement);
|
MoveToState(FetchAddressRegisterIndirectWithIndex8bitDisplacement_bw);
|
||||||
case Mode::ProgramCounterIndirectWithDisplacement:
|
case Mode::ProgramCounterIndirectWithDisplacement:
|
||||||
MoveToState(FetchProgramCounterIndirectWithDisplacement);
|
MoveToState(FetchProgramCounterIndirectWithDisplacement_bw);
|
||||||
case Mode::ProgramCounterIndirectWithIndex8bitDisplacement:
|
case Mode::ProgramCounterIndirectWithIndex8bitDisplacement:
|
||||||
MoveToState(FetchProgramCounterIndirectWithIndex8bitDisplacement);
|
MoveToState(FetchProgramCounterIndirectWithIndex8bitDisplacement_bw);
|
||||||
case Mode::AbsoluteShort:
|
case Mode::AbsoluteShort:
|
||||||
MoveToState(FetchAbsoluteShort);
|
MoveToState(FetchAbsoluteShort_bw);
|
||||||
case Mode::AbsoluteLong:
|
case Mode::AbsoluteLong:
|
||||||
MoveToState(FetchAbsoluteLong);
|
MoveToState(FetchAbsoluteLong_bw);
|
||||||
case Mode::ImmediateData:
|
case Mode::ImmediateData:
|
||||||
MoveToState(FetchImmediateData);
|
MoveToState(FetchImmediateData_bw);
|
||||||
|
|
||||||
// Should be impossible to reach.
|
// Should be impossible to reach.
|
||||||
default:
|
default:
|
||||||
@ -341,6 +354,71 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// As above, but for .l.
|
||||||
|
BeginState(FetchOperand_l):
|
||||||
|
if(!(operand_flags_ & (1 << next_operand_))) {
|
||||||
|
state_ = perform_state_;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(instruction_.mode(next_operand_)) {
|
||||||
|
case Mode::AddressRegisterDirect:
|
||||||
|
case Mode::DataRegisterDirect:
|
||||||
|
operand_[next_operand_] = registers_[instruction_.lreg(next_operand_)];
|
||||||
|
MoveToNextOperand(FetchOperand_bw);
|
||||||
|
|
||||||
|
case Mode::Quick:
|
||||||
|
operand_[next_operand_].l = InstructionSet::M68k::quick(opcode_, instruction_.operation);
|
||||||
|
MoveToNextOperand(FetchOperand_bw);
|
||||||
|
|
||||||
|
case Mode::AddressRegisterIndirect:
|
||||||
|
MoveToState(FetchAddressRegisterIndirect_l);
|
||||||
|
case Mode::AddressRegisterIndirectWithPostincrement:
|
||||||
|
MoveToState(FetchAddressRegisterIndirectWithPostincrement_l);
|
||||||
|
case Mode::AddressRegisterIndirectWithPredecrement:
|
||||||
|
MoveToState(FetchAddressRegisterIndirectWithPredecrement_l);
|
||||||
|
case Mode::AddressRegisterIndirectWithDisplacement:
|
||||||
|
MoveToState(FetchAddressRegisterIndirectWithDisplacement_l);
|
||||||
|
case Mode::AddressRegisterIndirectWithIndex8bitDisplacement:
|
||||||
|
MoveToState(FetchAddressRegisterIndirectWithIndex8bitDisplacement_l);
|
||||||
|
case Mode::ProgramCounterIndirectWithDisplacement:
|
||||||
|
MoveToState(FetchProgramCounterIndirectWithDisplacement_l);
|
||||||
|
case Mode::ProgramCounterIndirectWithIndex8bitDisplacement:
|
||||||
|
MoveToState(FetchProgramCounterIndirectWithIndex8bitDisplacement_l);
|
||||||
|
case Mode::AbsoluteShort:
|
||||||
|
MoveToState(FetchAbsoluteShort_l);
|
||||||
|
case Mode::AbsoluteLong:
|
||||||
|
MoveToState(FetchAbsoluteLong_l);
|
||||||
|
case Mode::ImmediateData:
|
||||||
|
MoveToState(FetchImmediateData_l);
|
||||||
|
|
||||||
|
// Should be impossible to reach.
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// MARK: - Fetch, addressing modes.
|
||||||
|
|
||||||
|
BeginState(FetchAddressRegisterIndirect_bw):
|
||||||
|
effective_address_[next_operand_] = registers_[8 + instruction_.reg(next_operand_)].l;
|
||||||
|
|
||||||
|
temporary_address_ = effective_address_[next_operand_];
|
||||||
|
Access(operand_[next_operand_].low); // nr
|
||||||
|
MoveToNextOperand(FetchOperand_bw);
|
||||||
|
|
||||||
|
BeginState(FetchAddressRegisterIndirect_l):
|
||||||
|
effective_address_[next_operand_] = registers_[8 + instruction_.reg(next_operand_)].l;
|
||||||
|
|
||||||
|
temporary_address_ = effective_address_[next_operand_];
|
||||||
|
Access(operand_[next_operand_].high); // nR
|
||||||
|
|
||||||
|
temporary_address_ += 2;
|
||||||
|
Access(operand_[next_operand_].low); // nr
|
||||||
|
MoveToNextOperand(FetchOperand_l);
|
||||||
|
|
||||||
|
// MARK: - Store.
|
||||||
|
|
||||||
// Store operand is a lot simpler: only one operand is ever stored, and its address
|
// Store operand is a lot simpler: only one operand is ever stored, and its address
|
||||||
// is already known. So this can either skip straight back to ::Decode if the target
|
// is already known. So this can either skip straight back to ::Decode if the target
|
||||||
// is a register, otherwise a single write operation can occur.
|
// is a register, otherwise a single write operation can occur.
|
||||||
@ -409,22 +487,30 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
#define TODOState(x) \
|
#define TODOState(x) \
|
||||||
BeginState(x): [[fallthrough]];
|
BeginState(x): [[fallthrough]];
|
||||||
|
|
||||||
TODOState(FetchAddressRegisterIndirect);
|
TODOState(FetchAddressRegisterIndirectWithPostincrement_bw);
|
||||||
TODOState(FetchAddressRegisterIndirectWithPostincrement);
|
TODOState(FetchAddressRegisterIndirectWithPredecrement_bw);
|
||||||
TODOState(FetchAddressRegisterIndirectWithPredecrement);
|
TODOState(FetchAddressRegisterIndirectWithDisplacement_bw);
|
||||||
TODOState(FetchAddressRegisterIndirectWithDisplacement);
|
TODOState(FetchAddressRegisterIndirectWithIndex8bitDisplacement_bw);
|
||||||
TODOState(FetchAddressRegisterIndirectWithIndex8bitDisplacement);
|
TODOState(FetchProgramCounterIndirectWithDisplacement_bw);
|
||||||
TODOState(FetchProgramCounterIndirectWithDisplacement);
|
TODOState(FetchProgramCounterIndirectWithIndex8bitDisplacement_bw);
|
||||||
TODOState(FetchProgramCounterIndirectWithIndex8bitDisplacement);
|
TODOState(FetchAbsoluteShort_bw);
|
||||||
TODOState(FetchAbsoluteShort);
|
TODOState(FetchAbsoluteLong_bw);
|
||||||
TODOState(FetchAbsoluteLong);
|
TODOState(FetchImmediateData_bw);
|
||||||
TODOState(FetchImmediateData);
|
|
||||||
TODOState(FetchOperandl);
|
TODOState(FetchAddressRegisterIndirectWithPostincrement_l);
|
||||||
|
TODOState(FetchAddressRegisterIndirectWithPredecrement_l);
|
||||||
|
TODOState(FetchAddressRegisterIndirectWithDisplacement_l);
|
||||||
|
TODOState(FetchAddressRegisterIndirectWithIndex8bitDisplacement_l);
|
||||||
|
TODOState(FetchProgramCounterIndirectWithDisplacement_l);
|
||||||
|
TODOState(FetchProgramCounterIndirectWithIndex8bitDisplacement_l);
|
||||||
|
TODOState(FetchAbsoluteShort_l);
|
||||||
|
TODOState(FetchAbsoluteLong_l);
|
||||||
|
TODOState(FetchImmediateData_l);
|
||||||
|
|
||||||
#undef TODOState
|
#undef TODOState
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("Unhandled state: %d\n", state_);
|
printf("Unhandled state: %d; opcode is %04x\n", state_, opcode_);
|
||||||
assert(false);
|
assert(false);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user