1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Implement the complete set of fetch addressing modes.

Subject to observations: (1) MOVE uses slightly custom versions of many of these for its stores; and (2) PEA and LEA need to do the calculation but not the read, so some of this will be duplicated further. It's either that or include greater conditionality on the path.
This commit is contained in:
Thomas Harte 2022-05-19 15:03:22 -04:00
parent e4c0a89889
commit 0471decfc8
2 changed files with 243 additions and 37 deletions

View File

@ -258,9 +258,12 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
next_operand_ = 0; next_operand_ = 0;
// Obtain operand flags and pick a perform pattern. // Obtain operand flags and pick a perform pattern.
#define CASE(x, y) \ #define CASE(x) \
case InstructionSet::M68k::Operation::x: \ case InstructionSet::M68k::Operation::x: \
operand_flags_ = InstructionSet::M68k::operand_flags<InstructionSet::M68k::Model::M68000, InstructionSet::M68k::Operation::x>(); \ operand_flags_ = InstructionSet::M68k::operand_flags<InstructionSet::M68k::Model::M68000, InstructionSet::M68k::Operation::x>();
#define StdCASE(x, y) \
CASE(x) \
y; \ y; \
\ \
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) { \
@ -276,7 +279,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
} }
switch(instruction_.operation) { switch(instruction_.operation) {
CASE(NBCD, { StdCASE(NBCD, {
if(instruction_.mode(0) == Mode::DataRegisterDirect) { if(instruction_.mode(0) == Mode::DataRegisterDirect) {
perform_state_ = Perform_np_n; perform_state_ = Perform_np_n;
} else { } else {
@ -284,17 +287,20 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
} }
}) })
CASE(SWAP, perform_state_ = Perform_np); StdCASE(SWAP, perform_state_ = Perform_np);
CASE(MOVEw, perform_state_ = MOVEw); StdCASE(MOVEw, perform_state_ = MOVEw);
CASE(CMPb, perform_state_ = Perform_np); StdCASE(CMPb, perform_state_ = Perform_np);
CASE(CMPw, perform_state_ = Perform_np); StdCASE(CMPw, perform_state_ = Perform_np);
CASE(CMPl, perform_state_ = Perform_np_n); StdCASE(CMPl, perform_state_ = Perform_np_n);
CASE(ANDb, perform_state_ = Perform_np); StdCASE(CMPAw, perform_state_ = Perform_np_n);
CASE(ANDw, perform_state_ = Perform_np); StdCASE(CMPAl, perform_state_ = Perform_np_n);
CASE(ANDl, {
StdCASE(ANDb, perform_state_ = Perform_np);
StdCASE(ANDw, perform_state_ = Perform_np);
StdCASE(ANDl, {
if(instruction_.mode(1) == Mode::DataRegisterDirect) { if(instruction_.mode(1) == Mode::DataRegisterDirect) {
switch(instruction_.mode(0)) { switch(instruction_.mode(0)) {
default: default:
@ -310,9 +316,9 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
} }
}); });
CASE(ORb, perform_state_ = Perform_np); StdCASE(ORb, perform_state_ = Perform_np);
CASE(ORw, perform_state_ = Perform_np); StdCASE(ORw, perform_state_ = Perform_np);
CASE(ORl, { StdCASE(ORl, {
if(instruction_.mode(1) == Mode::DataRegisterDirect) { if(instruction_.mode(1) == Mode::DataRegisterDirect) {
switch(instruction_.mode(0)) { switch(instruction_.mode(0)) {
default: default:
@ -328,9 +334,9 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
} }
}); });
CASE(EORb, perform_state_ = Perform_np); StdCASE(EORb, perform_state_ = Perform_np);
CASE(EORw, perform_state_ = Perform_np); StdCASE(EORw, perform_state_ = Perform_np);
CASE(EORl, { StdCASE(EORl, {
if(instruction_.mode(1) == Mode::DataRegisterDirect) { if(instruction_.mode(1) == Mode::DataRegisterDirect) {
perform_state_ = Perform_np_nn; perform_state_ = Perform_np_nn;
} else { } else {
@ -452,6 +458,9 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
// MARK: - Fetch, addressing modes. // MARK: - Fetch, addressing modes.
//
// AddressRegisterIndirect
//
BeginState(FetchAddressRegisterIndirect_bw): BeginState(FetchAddressRegisterIndirect_bw):
effective_address_[next_operand_] = registers_[8 + instruction_.reg(next_operand_)].l; effective_address_[next_operand_] = registers_[8 + instruction_.reg(next_operand_)].l;
SetDataAddress(effective_address_[next_operand_]); SetDataAddress(effective_address_[next_operand_]);
@ -459,7 +468,6 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
Access(operand_[next_operand_].low); // nr Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_bw); MoveToNextOperand(FetchOperand_bw);
// TODO: avoid use of temporary_address_ here and probably above.
BeginState(FetchAddressRegisterIndirect_l): BeginState(FetchAddressRegisterIndirect_l):
effective_address_[next_operand_] = registers_[8 + instruction_.reg(next_operand_)].l; effective_address_[next_operand_] = registers_[8 + instruction_.reg(next_operand_)].l;
SetDataAddress(effective_address_[next_operand_]); SetDataAddress(effective_address_[next_operand_]);
@ -470,6 +478,217 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
Access(operand_[next_operand_].low); // nr Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_l); MoveToNextOperand(FetchOperand_l);
//
// AddressRegisterIndirectWithPostincrement
//
BeginState(FetchAddressRegisterIndirectWithPostincrement_bw):
effective_address_[next_operand_] = registers_[8 + instruction_.reg(next_operand_)].l;
registers_[8 + instruction_.reg(next_operand_)].l +=
byte_word_increments[int(instruction_.operand_size())][instruction_.reg(next_operand_)];
SetDataAddress(effective_address_[next_operand_]);
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_bw);
BeginState(FetchAddressRegisterIndirectWithPostincrement_l):
effective_address_[next_operand_] = registers_[8 + instruction_.reg(next_operand_)].l;
registers_[8 + instruction_.reg(next_operand_)].l += 4;
SetDataAddress(effective_address_[next_operand_]);
Access(operand_[next_operand_].high); // nR
effective_address_[next_operand_] += 2;
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_l);
//
// AddressRegisterIndirectWithPredecrement
//
BeginState(FetchAddressRegisterIndirectWithPredecrement_bw):
registers_[8 + instruction_.reg(next_operand_)].l -=
byte_word_increments[int(instruction_.operand_size())][instruction_.reg(next_operand_)];
effective_address_[next_operand_] = registers_[8 + instruction_.reg(next_operand_)].l;
SetDataAddress(effective_address_[next_operand_]);
IdleBus(1); // n
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_bw);
BeginState(FetchAddressRegisterIndirectWithPredecrement_l):
registers_[8 + instruction_.reg(next_operand_)].l -= 4;
effective_address_[next_operand_] = registers_[8 + instruction_.reg(next_operand_)].l;
SetDataAddress(effective_address_[next_operand_]);
IdleBus(1); // n
Access(operand_[next_operand_].high); // nR
effective_address_[next_operand_] += 2;
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_l);
//
// AddressRegisterIndirectWithDisplacement
//
BeginState(FetchAddressRegisterIndirectWithDisplacement_bw):
effective_address_[next_operand_] =
registers_[8 + instruction_.reg(next_operand_)].l +
int16_t(prefetch_.w);
SetDataAddress(effective_address_[next_operand_]);
Prefetch(); // np
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_bw);
BeginState(FetchAddressRegisterIndirectWithDisplacement_l):
effective_address_[next_operand_] =
registers_[8 + instruction_.reg(next_operand_)].l +
int16_t(prefetch_.w);
SetDataAddress(effective_address_[next_operand_]);
Prefetch(); // np
Access(operand_[next_operand_].high); // nR
effective_address_[next_operand_] += 2;
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_l);
//
// ProgramCounterIndirectWithDisplacement
//
BeginState(FetchProgramCounterIndirectWithDisplacement_bw):
effective_address_[next_operand_] =
instruction_address_ + 2 +
int16_t(prefetch_.w);
SetDataAddress(effective_address_[next_operand_]);
Prefetch(); // np
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_bw);
BeginState(FetchProgramCounterIndirectWithDisplacement_l):
effective_address_[next_operand_] =
instruction_address_ + 2 +
int16_t(prefetch_.w);
SetDataAddress(effective_address_[next_operand_]);
Prefetch(); // np
Access(operand_[next_operand_].high); // nR
effective_address_[next_operand_] += 2;
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_l);
#define d8Xn(base) \
base + \
((prefetch_.w & 0x800) ? \
registers_[prefetch_.w >> 12].l : \
int16_t(registers_[prefetch_.w >> 12].w)) + \
int8_t(prefetch_.b);
//
// AddressRegisterIndirectWithIndex8bitDisplacement
//
BeginState(FetchAddressRegisterIndirectWithIndex8bitDisplacement_bw):
effective_address_[next_operand_] = d8Xn(registers_[8 + instruction_.reg(next_operand_)].l);
SetDataAddress(effective_address_[next_operand_]);
IdleBus(1); // n
Prefetch(); // np
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_bw);
BeginState(FetchAddressRegisterIndirectWithIndex8bitDisplacement_l):
effective_address_[next_operand_] = d8Xn(registers_[8 + instruction_.reg(next_operand_)].l);
SetDataAddress(effective_address_[next_operand_]);
IdleBus(1); // n
Prefetch(); // np
Access(operand_[next_operand_].high); // nR
effective_address_[next_operand_] += 2;
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_l);
//
// ProgramCounterIndirectWithIndex8bitDisplacement
//
BeginState(FetchProgramCounterIndirectWithIndex8bitDisplacement_bw):
effective_address_[next_operand_] = d8Xn(instruction_address_ + 2);
SetDataAddress(effective_address_[next_operand_]);
IdleBus(1); // n
Prefetch(); // np
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_bw);
BeginState(FetchProgramCounterIndirectWithIndex8bitDisplacement_l):
effective_address_[next_operand_] = d8Xn(instruction_address_ + 2);;
SetDataAddress(effective_address_[next_operand_]);
IdleBus(1); // n
Prefetch(); // np
Access(operand_[next_operand_].high); // nR
effective_address_[next_operand_] += 2;
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_l);
#undef d8Xn
//
// AbsoluteShort
//
BeginState(FetchAbsoluteShort_bw):
effective_address_[next_operand_] = int16_t(prefetch_.w);
SetDataAddress(effective_address_[next_operand_]);
Prefetch(); // np
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_bw);
BeginState(FetchAbsoluteShort_l):
effective_address_[next_operand_] = int16_t(prefetch_.w);
SetDataAddress(effective_address_[next_operand_]);
Prefetch(); // np
Access(operand_[next_operand_].high); // nR
effective_address_[next_operand_] += 2;
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_l);
//
// AbsoluteLong
//
BeginState(FetchAbsoluteLong_bw):
Prefetch(); // np
effective_address_[next_operand_] = prefetch_.l;
SetDataAddress(effective_address_[next_operand_]);
Prefetch(); // np
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_bw);
BeginState(FetchAbsoluteLong_l):
Prefetch(); // np
effective_address_[next_operand_] = prefetch_.l;
SetDataAddress(effective_address_[next_operand_]);
Prefetch(); // np
Access(operand_[next_operand_].high); // nR
effective_address_[next_operand_] += 2;
Access(operand_[next_operand_].low); // nr
MoveToNextOperand(FetchOperand_l);
//
// ImmediateData
//
BeginState(FetchImmediateData_bw):
operand_[next_operand_].w = prefetch_.w;
Prefetch(); // np
MoveToNextOperand(FetchOperand_bw);
BeginState(FetchImmediateData_l):
Prefetch(); // np
operand_[next_operand_].l = prefetch_.l;
Prefetch(); // np
MoveToNextOperand(FetchOperand_l);
// MARK: - Store. // 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
@ -563,25 +782,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
#define TODOState(x) \ #define TODOState(x) \
BeginState(x): [[fallthrough]]; BeginState(x): [[fallthrough]];
TODOState(FetchAddressRegisterIndirectWithPostincrement_bw); // TODOState(FetchImmediateData_l);
TODOState(FetchAddressRegisterIndirectWithPredecrement_bw);
TODOState(FetchAddressRegisterIndirectWithDisplacement_bw);
TODOState(FetchAddressRegisterIndirectWithIndex8bitDisplacement_bw);
TODOState(FetchProgramCounterIndirectWithDisplacement_bw);
TODOState(FetchProgramCounterIndirectWithIndex8bitDisplacement_bw);
TODOState(FetchAbsoluteShort_bw);
TODOState(FetchAbsoluteLong_bw);
TODOState(FetchImmediateData_bw);
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

View File

@ -84,6 +84,11 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
// Flow controller... all TODO. // Flow controller... all TODO.
using Preinstruction = InstructionSet::M68k::Preinstruction; using Preinstruction = InstructionSet::M68k::Preinstruction;
static constexpr uint32_t byte_word_increments[2][8] = {
{ 1, 1, 1, 1, 1, 1, 1, 2, },
{ 2, 2, 2, 2, 2, 2, 2, 2, }
};
template <typename IntT> void did_mulu(IntT) {} template <typename IntT> void did_mulu(IntT) {}
template <typename IntT> void did_muls(IntT) {} template <typename IntT> void did_muls(IntT) {}
void did_chk(bool, bool) {} void did_chk(bool, bool) {}