mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-22 12:33:29 +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:
parent
e4c0a89889
commit
0471decfc8
@ -258,9 +258,12 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
||||
next_operand_ = 0;
|
||||
|
||||
// Obtain operand flags and pick a perform pattern.
|
||||
#define CASE(x, y) \
|
||||
#define CASE(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; \
|
||||
\
|
||||
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) {
|
||||
CASE(NBCD, {
|
||||
StdCASE(NBCD, {
|
||||
if(instruction_.mode(0) == Mode::DataRegisterDirect) {
|
||||
perform_state_ = Perform_np_n;
|
||||
} 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);
|
||||
CASE(CMPw, perform_state_ = Perform_np);
|
||||
CASE(CMPl, perform_state_ = Perform_np_n);
|
||||
StdCASE(CMPb, perform_state_ = Perform_np);
|
||||
StdCASE(CMPw, perform_state_ = Perform_np);
|
||||
StdCASE(CMPl, perform_state_ = Perform_np_n);
|
||||
|
||||
CASE(ANDb, perform_state_ = Perform_np);
|
||||
CASE(ANDw, perform_state_ = Perform_np);
|
||||
CASE(ANDl, {
|
||||
StdCASE(CMPAw, perform_state_ = Perform_np_n);
|
||||
StdCASE(CMPAl, perform_state_ = Perform_np_n);
|
||||
|
||||
StdCASE(ANDb, perform_state_ = Perform_np);
|
||||
StdCASE(ANDw, perform_state_ = Perform_np);
|
||||
StdCASE(ANDl, {
|
||||
if(instruction_.mode(1) == Mode::DataRegisterDirect) {
|
||||
switch(instruction_.mode(0)) {
|
||||
default:
|
||||
@ -310,9 +316,9 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
||||
}
|
||||
});
|
||||
|
||||
CASE(ORb, perform_state_ = Perform_np);
|
||||
CASE(ORw, perform_state_ = Perform_np);
|
||||
CASE(ORl, {
|
||||
StdCASE(ORb, perform_state_ = Perform_np);
|
||||
StdCASE(ORw, perform_state_ = Perform_np);
|
||||
StdCASE(ORl, {
|
||||
if(instruction_.mode(1) == Mode::DataRegisterDirect) {
|
||||
switch(instruction_.mode(0)) {
|
||||
default:
|
||||
@ -328,9 +334,9 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
||||
}
|
||||
});
|
||||
|
||||
CASE(EORb, perform_state_ = Perform_np);
|
||||
CASE(EORw, perform_state_ = Perform_np);
|
||||
CASE(EORl, {
|
||||
StdCASE(EORb, perform_state_ = Perform_np);
|
||||
StdCASE(EORw, perform_state_ = Perform_np);
|
||||
StdCASE(EORl, {
|
||||
if(instruction_.mode(1) == Mode::DataRegisterDirect) {
|
||||
perform_state_ = Perform_np_nn;
|
||||
} else {
|
||||
@ -452,6 +458,9 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
||||
|
||||
// MARK: - Fetch, addressing modes.
|
||||
|
||||
//
|
||||
// AddressRegisterIndirect
|
||||
//
|
||||
BeginState(FetchAddressRegisterIndirect_bw):
|
||||
effective_address_[next_operand_] = registers_[8 + instruction_.reg(next_operand_)].l;
|
||||
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
|
||||
MoveToNextOperand(FetchOperand_bw);
|
||||
|
||||
// TODO: avoid use of temporary_address_ here and probably above.
|
||||
BeginState(FetchAddressRegisterIndirect_l):
|
||||
effective_address_[next_operand_] = registers_[8 + instruction_.reg(next_operand_)].l;
|
||||
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
|
||||
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.
|
||||
|
||||
// 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) \
|
||||
BeginState(x): [[fallthrough]];
|
||||
|
||||
TODOState(FetchAddressRegisterIndirectWithPostincrement_bw);
|
||||
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);
|
||||
// TODOState(FetchImmediateData_l);
|
||||
|
||||
#undef TODOState
|
||||
|
||||
|
@ -84,6 +84,11 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
|
||||
// Flow controller... all TODO.
|
||||
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_muls(IntT) {}
|
||||
void did_chk(bool, bool) {}
|
||||
|
Loading…
Reference in New Issue
Block a user