mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-16 18:30:32 +00:00
Simplify address handling; add perform patterns for CMP, AND, OR, EOR.
This commit is contained in:
parent
274902c3c1
commit
084d6ca11d
@ -61,6 +61,7 @@ enum ExecutionState: int {
|
|||||||
|
|
||||||
Perform_np,
|
Perform_np,
|
||||||
Perform_np_n,
|
Perform_np_n,
|
||||||
|
Perform_np_nn,
|
||||||
|
|
||||||
// MOVE has unique bus usage, so has specialised states.
|
// MOVE has unique bus usage, so has specialised states.
|
||||||
|
|
||||||
@ -165,12 +166,15 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
WaitForDTACK(announce); \
|
WaitForDTACK(announce); \
|
||||||
CompleteAccess(perform);
|
CompleteAccess(perform);
|
||||||
|
|
||||||
// Sets up the next data access — its address and size/read flags.
|
// Sets up the next data access size and read flags.
|
||||||
#define SetupDataAccess(addr, read_flag, select_flag) \
|
#define SetupDataAccess(read_flag, select_flag) \
|
||||||
access.address = access_announce.address = &addr; \
|
|
||||||
access_announce.operation = Microcycle::NewAddress | Microcycle::IsData | (read_flag); \
|
access_announce.operation = Microcycle::NewAddress | Microcycle::IsData | (read_flag); \
|
||||||
access.operation = access_announce.operation | (select_flag);
|
access.operation = access_announce.operation | (select_flag);
|
||||||
|
|
||||||
|
// Sets the address source for the next data access.
|
||||||
|
#define SetDataAddress(addr) \
|
||||||
|
access.address = access_announce.address = &addr;
|
||||||
|
|
||||||
// Performs the access established by SetupDataAccess into val.
|
// Performs the access established by SetupDataAccess into val.
|
||||||
#define Access(val) \
|
#define Access(val) \
|
||||||
AccessPair(val, access_announce, access)
|
AccessPair(val, access_announce, access)
|
||||||
@ -214,7 +218,8 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
status_.trace_flag = 0;
|
status_.trace_flag = 0;
|
||||||
did_update_status();
|
did_update_status();
|
||||||
|
|
||||||
SetupDataAccess(temporary_address_, Microcycle::Read, Microcycle::SelectWord);
|
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord);
|
||||||
|
SetDataAddress(temporary_address_);
|
||||||
|
|
||||||
temporary_address_ = 0;
|
temporary_address_ = 0;
|
||||||
Access(registers_[15].high); // nF
|
Access(registers_[15].high); // nF
|
||||||
@ -253,39 +258,85 @@ 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) \
|
#define CASE(x, y) \
|
||||||
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>(); \
|
||||||
|
y; \
|
||||||
#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(Microcycle::Read, Microcycle::SelectWord); \
|
||||||
MoveToState(FetchOperand_l); \
|
MoveToState(FetchOperand_l); \
|
||||||
} else { \
|
|
||||||
if constexpr (InstructionSet::M68k::operand_size<InstructionSet::M68k::Operation::x>() == InstructionSet::M68k::DataSize::Byte) { \
|
|
||||||
SetupDataAccess(temporary_address_, Microcycle::Read, Microcycle::SelectByte); \
|
|
||||||
} else { \
|
} else { \
|
||||||
SetupDataAccess(temporary_address_, Microcycle::Read, Microcycle::SelectWord); \
|
if constexpr (InstructionSet::M68k::operand_size<InstructionSet::M68k::Operation::x>() == InstructionSet::M68k::DataSize::Byte) { \
|
||||||
} \
|
SetupDataAccess(Microcycle::Read, Microcycle::SelectByte); \
|
||||||
MoveToState(FetchOperand_bw); \
|
} else { \
|
||||||
}
|
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord); \
|
||||||
|
} \
|
||||||
|
MoveToState(FetchOperand_bw); \
|
||||||
|
}
|
||||||
|
|
||||||
switch(instruction_.operation) {
|
switch(instruction_.operation) {
|
||||||
CASE(NBCD)
|
CASE(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 {
|
||||||
perform_state_ = Perform_np;
|
perform_state_ = Perform_np;
|
||||||
}
|
}
|
||||||
FetchOperands(NBCD)
|
})
|
||||||
|
|
||||||
CASE(SWAP)
|
CASE(SWAP, perform_state_ = Perform_np);
|
||||||
perform_state_ = Perform_np;
|
|
||||||
FetchOperands(SWAP)
|
|
||||||
|
|
||||||
CASE(MOVEw)
|
CASE(MOVEw, perform_state_ = MOVEw);
|
||||||
perform_state_ = MOVEw;
|
|
||||||
FetchOperands(MOVEw)
|
CASE(CMPb, perform_state_ = Perform_np);
|
||||||
|
CASE(CMPw, perform_state_ = Perform_np);
|
||||||
|
CASE(CMPl, perform_state_ = Perform_np_n);
|
||||||
|
|
||||||
|
CASE(ANDb, perform_state_ = Perform_np);
|
||||||
|
CASE(ANDw, perform_state_ = Perform_np);
|
||||||
|
CASE(ANDl, {
|
||||||
|
if(instruction_.mode(1) == Mode::DataRegisterDirect) {
|
||||||
|
switch(instruction_.mode(0)) {
|
||||||
|
default:
|
||||||
|
perform_state_ = Perform_np_n;
|
||||||
|
break;
|
||||||
|
case Mode::DataRegisterDirect:
|
||||||
|
case Mode::ImmediateData:
|
||||||
|
perform_state_ = Perform_np_nn;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
perform_state_ = Perform_np;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
CASE(ORb, perform_state_ = Perform_np);
|
||||||
|
CASE(ORw, perform_state_ = Perform_np);
|
||||||
|
CASE(ORl, {
|
||||||
|
if(instruction_.mode(1) == Mode::DataRegisterDirect) {
|
||||||
|
switch(instruction_.mode(0)) {
|
||||||
|
default:
|
||||||
|
perform_state_ = Perform_np_n;
|
||||||
|
break;
|
||||||
|
case Mode::DataRegisterDirect:
|
||||||
|
case Mode::ImmediateData:
|
||||||
|
perform_state_ = Perform_np_nn;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
perform_state_ = Perform_np;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
CASE(EORb, perform_state_ = Perform_np);
|
||||||
|
CASE(EORw, perform_state_ = Perform_np);
|
||||||
|
CASE(EORl, {
|
||||||
|
if(instruction_.mode(1) == Mode::DataRegisterDirect) {
|
||||||
|
perform_state_ = Perform_np_nn;
|
||||||
|
} else {
|
||||||
|
perform_state_ = Perform_np;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
@ -403,19 +454,18 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
|
|
||||||
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_]);
|
||||||
|
|
||||||
temporary_address_ = effective_address_[next_operand_];
|
|
||||||
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.
|
// 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_]);
|
||||||
|
|
||||||
temporary_address_ = effective_address_[next_operand_];
|
|
||||||
Access(operand_[next_operand_].high); // nR
|
Access(operand_[next_operand_].high); // nR
|
||||||
|
|
||||||
temporary_address_ += 2;
|
|
||||||
effective_address_[next_operand_] += 2;
|
effective_address_[next_operand_] += 2;
|
||||||
Access(operand_[next_operand_].low); // nr
|
Access(operand_[next_operand_].low); // nr
|
||||||
MoveToNextOperand(FetchOperand_l);
|
MoveToNextOperand(FetchOperand_l);
|
||||||
@ -436,14 +486,15 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetupDataAccess(
|
SetupDataAccess(
|
||||||
effective_address_[next_operand_],
|
|
||||||
0,
|
0,
|
||||||
(instruction_.operand_size() == InstructionSet::M68k::DataSize::Byte) ? Microcycle::SelectByte : Microcycle::SelectWord);
|
(instruction_.operand_size() == InstructionSet::M68k::DataSize::Byte) ? Microcycle::SelectByte : Microcycle::SelectWord);
|
||||||
|
SetDataAddress(effective_address_[next_operand_]);
|
||||||
Access(operand_[next_operand_].low); // nw
|
Access(operand_[next_operand_].low); // nw
|
||||||
MoveToState(Decode);
|
MoveToState(Decode);
|
||||||
|
|
||||||
BeginState(StoreOperand_l):
|
BeginState(StoreOperand_l):
|
||||||
SetupDataAccess(effective_address_[next_operand_], 0, Microcycle::SelectWord);
|
SetupDataAccess(0, Microcycle::SelectWord);
|
||||||
|
SetDataAddress(effective_address_[next_operand_]);
|
||||||
Access(operand_[next_operand_].low); // nw
|
Access(operand_[next_operand_].low); // nw
|
||||||
|
|
||||||
effective_address_[next_operand_] -= 2;
|
effective_address_[next_operand_] -= 2;
|
||||||
@ -470,6 +521,13 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
IdleBus(1); // n
|
IdleBus(1); // n
|
||||||
MoveToWritePhase();
|
MoveToWritePhase();
|
||||||
|
|
||||||
|
BeginState(Perform_np_nn):
|
||||||
|
InstructionSet::M68k::perform<InstructionSet::M68k::Model::M68000>(
|
||||||
|
instruction_, operand_[0], operand_[1], status_, *static_cast<ProcessorBase *>(this));
|
||||||
|
Prefetch(); // np
|
||||||
|
IdleBus(2); // nn
|
||||||
|
MoveToWritePhase();
|
||||||
|
|
||||||
#undef MoveToWritePhase
|
#undef MoveToWritePhase
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user