1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-11 04:28:58 +00:00

Add AddressRegisterIndirect fetches.

This commit is contained in:
Thomas Harte 2022-05-19 10:47:57 -04:00
parent c6c6213460
commit f46e7c65c5

View File

@ -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);
}} }}