mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-27 01:31:42 +00:00
Merge branch '68000Mk2' into InMacintosh
This commit is contained in:
commit
8c242fa2dd
@ -522,17 +522,18 @@ template <
|
|||||||
#define DIV(Type16, Type32, flow_function) { \
|
#define DIV(Type16, Type32, flow_function) { \
|
||||||
status.carry_flag = 0; \
|
status.carry_flag = 0; \
|
||||||
\
|
\
|
||||||
if(!src.w) { \
|
const auto dividend = Type32(dest.l); \
|
||||||
|
const auto divisor = Type32(Type16(src.w)); \
|
||||||
|
\
|
||||||
|
if(!divisor) { \
|
||||||
status.negative_flag = status.overflow_flag = 0; \
|
status.negative_flag = status.overflow_flag = 0; \
|
||||||
status.zero_result = 1; \
|
status.zero_result = 1; \
|
||||||
flow_controller.raise_exception(Exception::IntegerDivideByZero); \
|
flow_controller.raise_exception(Exception::IntegerDivideByZero); \
|
||||||
|
flow_controller.template flow_function<false>(dividend, divisor); \
|
||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
const auto dividend = Type32(dest.l); \
|
|
||||||
const auto divisor = Type32(Type16(src.w)); \
|
|
||||||
const auto quotient = dividend / divisor; \
|
const auto quotient = dividend / divisor; \
|
||||||
\
|
|
||||||
if(quotient != Type32(Type16(quotient))) { \
|
if(quotient != Type32(Type16(quotient))) { \
|
||||||
status.overflow_flag = 1; \
|
status.overflow_flag = 1; \
|
||||||
flow_controller.template flow_function<true>(dividend, divisor); \
|
flow_controller.template flow_function<true>(dividend, divisor); \
|
||||||
|
@ -61,7 +61,7 @@ std::string Preinstruction::to_string(int opcode) const {
|
|||||||
const char *instruction;
|
const char *instruction;
|
||||||
|
|
||||||
switch(operation) {
|
switch(operation) {
|
||||||
case Operation::Undefined: instruction = "None"; break;
|
case Operation::Undefined: return "None";
|
||||||
case Operation::NOP: instruction = "NOP"; break;
|
case Operation::NOP: instruction = "NOP"; break;
|
||||||
case Operation::ABCD: instruction = "ABCD"; break;
|
case Operation::ABCD: instruction = "ABCD"; break;
|
||||||
case Operation::SBCD: instruction = "SBCD"; break;
|
case Operation::SBCD: instruction = "SBCD"; break;
|
||||||
|
@ -95,6 +95,23 @@ struct Status {
|
|||||||
return is_supervisor;
|
return is_supervisor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adjusts the status for exception processing — sets supervisor mode, disables trace,
|
||||||
|
/// and if @c new_interrupt_level is greater than or equal to 0 sets that as the new
|
||||||
|
/// interrupt level.
|
||||||
|
///
|
||||||
|
/// @returns The status prior to those changes.
|
||||||
|
uint16_t begin_exception(int new_interrupt_level = -1) {
|
||||||
|
const uint16_t initial_status = status();
|
||||||
|
|
||||||
|
if(new_interrupt_level >= 0) {
|
||||||
|
interrupt_level = new_interrupt_level;
|
||||||
|
}
|
||||||
|
is_supervisor = true;
|
||||||
|
trace_flag = 0;
|
||||||
|
|
||||||
|
return initial_status;
|
||||||
|
}
|
||||||
|
|
||||||
/// Evaluates @c condition.
|
/// Evaluates @c condition.
|
||||||
bool evaluate_condition(Condition condition) {
|
bool evaluate_condition(Condition condition) {
|
||||||
switch(condition) {
|
switch(condition) {
|
||||||
|
@ -726,7 +726,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)performDIVS:(uint16_t)divisor d1:(uint32_t)d1 {
|
- (void)performDIVS:(uint16_t)divisor d1:(uint32_t)d1 {
|
||||||
[self performDIVS:divisor d1:d1];
|
[self performDIVS:divisor d1:d1 sp:0];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)performDIVSOverflowTestDivisor:(uint16_t)divisor {
|
- (void)performDIVSOverflowTestDivisor:(uint16_t)divisor {
|
||||||
@ -734,7 +734,12 @@
|
|||||||
|
|
||||||
const auto state = self.machine->get_processor_state();
|
const auto state = self.machine->get_processor_state();
|
||||||
XCTAssertEqual(state.registers.data[1], 0x4768f231);
|
XCTAssertEqual(state.registers.data[1], 0x4768f231);
|
||||||
XCTAssertEqual(state.registers.status & ConditionCode::AllConditions, ConditionCode::Extend | ConditionCode::Negative | ConditionCode::Overflow);
|
|
||||||
|
// N and Z are officially undefined upon DIVS overflow, and I've found no
|
||||||
|
// other relevant information.
|
||||||
|
XCTAssertEqual(
|
||||||
|
state.registers.status & (ConditionCode::Extend | ConditionCode::Overflow | ConditionCode::Carry),
|
||||||
|
ConditionCode::Extend | ConditionCode::Overflow);
|
||||||
XCTAssertEqual(20, self.machine->get_cycle_count());
|
XCTAssertEqual(20, self.machine->get_cycle_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,7 +870,7 @@
|
|||||||
XCTAssertEqual(state.registers.data[1], 0x1fffffff);
|
XCTAssertEqual(state.registers.data[1], 0x1fffffff);
|
||||||
XCTAssertEqual(state.registers.supervisor_stack_pointer, initial_sp - 6);
|
XCTAssertEqual(state.registers.supervisor_stack_pointer, initial_sp - 6);
|
||||||
XCTAssertEqual(state.registers.status & ConditionCode::AllConditions, ConditionCode::Extend);
|
XCTAssertEqual(state.registers.status & ConditionCode::AllConditions, ConditionCode::Extend);
|
||||||
XCTAssertEqual(42, self.machine->get_cycle_count());
|
XCTAssertEqual(44, self.machine->get_cycle_count());
|
||||||
|
|
||||||
// Check stack contents; should be PC.l, PC.h and status register.
|
// Check stack contents; should be PC.l, PC.h and status register.
|
||||||
// Assumed: the program counter on the stack is that of the
|
// Assumed: the program counter on the stack is that of the
|
||||||
|
@ -157,41 +157,48 @@
|
|||||||
XCTAssertEqual(state.registers.data[2], d2);
|
XCTAssertEqual(state.registers.data[2], d2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re: CHK, below; the final state of N is undocumented if Dn >= 0 and Dn < <ea>.
|
||||||
|
// Z, V and C are also undocumented by Motorola, but are documneted by 68knotes.txt.
|
||||||
|
|
||||||
- (void)testCHK_1111v1111 {
|
- (void)testCHK_1111v1111 {
|
||||||
[self performCHKd1:0x1111 d2:0x1111];
|
[self performCHKd1:0x1111 d2:0x1111]; // Neither exception-generating state applies.
|
||||||
|
|
||||||
const auto state = _machine->get_processor_state();
|
const auto state = _machine->get_processor_state();
|
||||||
XCTAssertEqual(state.registers.program_counter, 0x1002 + 4);
|
XCTAssertEqual(state.registers.program_counter, 0x1002 + 4);
|
||||||
XCTAssertEqual(state.registers.status & ConditionCode::AllConditions, ConditionCode::Extend);
|
XCTAssertEqual(
|
||||||
|
state.registers.status & (ConditionCode::Extend | ConditionCode::Zero | ConditionCode::Overflow | ConditionCode::Carry),
|
||||||
|
ConditionCode::Extend);
|
||||||
XCTAssertEqual(10, _machine->get_cycle_count());
|
XCTAssertEqual(10, _machine->get_cycle_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testCHK_1111v0000 {
|
- (void)testCHK_1111v0000 {
|
||||||
[self performCHKd1:0x1111 d2:0x0000];
|
[self performCHKd1:0x1111 d2:0x0000]; // Neither exception-generating state applies.
|
||||||
|
|
||||||
const auto state = _machine->get_processor_state();
|
const auto state = _machine->get_processor_state();
|
||||||
XCTAssertEqual(state.registers.program_counter, 0x1002 + 4);
|
XCTAssertEqual(state.registers.program_counter, 0x1002 + 4);
|
||||||
XCTAssertEqual(state.registers.status & ConditionCode::AllConditions, ConditionCode::Extend | ConditionCode::Zero);
|
XCTAssertEqual(
|
||||||
|
state.registers.status & (ConditionCode::Extend | ConditionCode::Zero | ConditionCode::Overflow | ConditionCode::Carry),
|
||||||
|
ConditionCode::Extend | ConditionCode::Zero);
|
||||||
XCTAssertEqual(10, _machine->get_cycle_count());
|
XCTAssertEqual(10, _machine->get_cycle_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testCHK_8000v8001 {
|
- (void)testCHK_8000v8001 {
|
||||||
[self performCHKd1:0x8000 d2:0x8001];
|
[self performCHKd1:0x8000 d2:0x8001]; // Both less than 0 and D2 greater than D1.
|
||||||
|
|
||||||
const auto state = _machine->get_processor_state();
|
const auto state = _machine->get_processor_state();
|
||||||
XCTAssertNotEqual(state.registers.program_counter, 0x1002 + 4);
|
XCTAssertNotEqual(state.registers.program_counter, 0x1002 + 4);
|
||||||
XCTAssertEqual(state.registers.stack_pointer(), 0xfffffffa);
|
XCTAssertEqual(state.registers.stack_pointer(), 0xfffffffa);
|
||||||
XCTAssertEqual(state.registers.status & ConditionCode::AllConditions, ConditionCode::Extend);
|
XCTAssertEqual(state.registers.status & ConditionCode::AllConditions, ConditionCode::Extend | ConditionCode::Negative);
|
||||||
XCTAssertEqual(42, _machine->get_cycle_count());
|
XCTAssertEqual(38, _machine->get_cycle_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testCHK_8000v8000 {
|
- (void)testCHK_8000v8000 {
|
||||||
[self performCHKd1:0x8000 d2:0x8000];
|
[self performCHKd1:0x8000 d2:0x8000]; // Less than 0.
|
||||||
|
|
||||||
const auto state = _machine->get_processor_state();
|
const auto state = _machine->get_processor_state();
|
||||||
XCTAssertNotEqual(state.registers.program_counter, 0x1002 + 4);
|
XCTAssertNotEqual(state.registers.program_counter, 0x1002 + 4);
|
||||||
XCTAssertEqual(state.registers.status & ConditionCode::AllConditions, ConditionCode::Extend | ConditionCode::Negative);
|
XCTAssertEqual(state.registers.status & ConditionCode::AllConditions, ConditionCode::Extend | ConditionCode::Negative);
|
||||||
XCTAssertEqual(44, _machine->get_cycle_count());
|
XCTAssertEqual(40, _machine->get_cycle_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: DBcc
|
// MARK: DBcc
|
||||||
|
@ -91,12 +91,16 @@ enum ExecutionState: int {
|
|||||||
CalcAddressRegisterIndirectWithPostincrement, // -
|
CalcAddressRegisterIndirectWithPostincrement, // -
|
||||||
CalcAddressRegisterIndirectWithPredecrement, // -
|
CalcAddressRegisterIndirectWithPredecrement, // -
|
||||||
CalcAddressRegisterIndirectWithDisplacement, // np
|
CalcAddressRegisterIndirectWithDisplacement, // np
|
||||||
CalcAddressRegisterIndirectWithIndex8bitDisplacement, // n np n
|
CalcAddressRegisterIndirectWithIndex8bitDisplacement, // np n
|
||||||
CalcProgramCounterIndirectWithDisplacement, // np
|
CalcProgramCounterIndirectWithDisplacement, // np
|
||||||
CalcProgramCounterIndirectWithIndex8bitDisplacement, // n np n
|
CalcProgramCounterIndirectWithIndex8bitDisplacement, // np n
|
||||||
CalcAbsoluteShort, // np
|
CalcAbsoluteShort, // np
|
||||||
CalcAbsoluteLong, // np np
|
CalcAbsoluteLong, // np np
|
||||||
|
|
||||||
|
CalcEffectiveAddressIdleFor8bitDisplacement, // As per CalcEffectiveAddress unless one of the
|
||||||
|
// 8-bit displacement modes is in use, in which case
|
||||||
|
// an extra idle bus state is prefixed.
|
||||||
|
|
||||||
// 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
|
||||||
// indicated bus cycle.
|
// indicated bus cycle.
|
||||||
@ -355,9 +359,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
IdleBus(7); // (n-)*5 nn
|
IdleBus(7); // (n-)*5 nn
|
||||||
|
|
||||||
// Establish general reset state.
|
// Establish general reset state.
|
||||||
status_.is_supervisor = true;
|
status_.begin_exception(7);
|
||||||
status_.interrupt_level = 7;
|
|
||||||
status_.trace_flag = 0;
|
|
||||||
should_trace_ = 0;
|
should_trace_ = 0;
|
||||||
did_update_status();
|
did_update_status();
|
||||||
|
|
||||||
@ -383,11 +385,8 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
|
|
||||||
// Perform a 'standard' exception, i.e. a Group 1 or 2.
|
// Perform a 'standard' exception, i.e. a Group 1 or 2.
|
||||||
BeginState(StandardException):
|
BeginState(StandardException):
|
||||||
captured_status_.w = status_.status();
|
|
||||||
|
|
||||||
// Switch to supervisor mode, disable interrupts.
|
// Switch to supervisor mode, disable interrupts.
|
||||||
status_.is_supervisor = true;
|
captured_status_.w = status_.begin_exception();
|
||||||
status_.trace_flag = 0;
|
|
||||||
should_trace_ = 0;
|
should_trace_ = 0;
|
||||||
did_update_status();
|
did_update_status();
|
||||||
|
|
||||||
@ -451,13 +450,10 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
// 4) function code;
|
// 4) function code;
|
||||||
// 5) access address?
|
// 5) access address?
|
||||||
|
|
||||||
captured_status_.w = status_.status();
|
|
||||||
IdleBus(2);
|
IdleBus(2);
|
||||||
|
|
||||||
// Switch to supervisor mode, disable interrupts.
|
// Switch to supervisor mode, disable interrupts.
|
||||||
status_.is_supervisor = true;
|
captured_status_.w = status_.begin_exception(7);
|
||||||
status_.trace_flag = 0;
|
|
||||||
status_.interrupt_level = 7;
|
|
||||||
should_trace_ = 0;
|
should_trace_ = 0;
|
||||||
did_update_status();
|
did_update_status();
|
||||||
|
|
||||||
@ -515,10 +511,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
IdleBus(3); // n nn
|
IdleBus(3); // n nn
|
||||||
|
|
||||||
// Capture status and switch to supervisor mode.
|
// Capture status and switch to supervisor mode.
|
||||||
captured_status_.w = status_.status();
|
captured_status_.w = status_.begin_exception(captured_interrupt_level_);
|
||||||
status_.is_supervisor = true;
|
|
||||||
status_.trace_flag = 0;
|
|
||||||
status_.interrupt_level = captured_interrupt_level_;
|
|
||||||
should_trace_ = 0;
|
should_trace_ = 0;
|
||||||
did_update_status();
|
did_update_status();
|
||||||
|
|
||||||
@ -602,18 +595,21 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
bus_handler_.will_perform(instruction_address_.l, opcode_);
|
bus_handler_.will_perform(instruction_address_.l, opcode_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for a privilege violation.
|
|
||||||
if(instruction_.requires_supervisor() && !status_.is_supervisor) {
|
|
||||||
exception_vector_ = InstructionSet::M68k::Exception::PrivilegeViolation;
|
|
||||||
MoveToStateSpecific(StandardException);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the first parameter is next fetched.
|
// Ensure the first parameter is next fetched.
|
||||||
next_operand_ = 0;
|
next_operand_ = 0;
|
||||||
|
|
||||||
// Obtain operand flags and pick a perform pattern.
|
/// If operation x requires supervisor privileges, checks whether the user is currently in supervisor mode;
|
||||||
|
/// if not then raises a privilege violation exception.
|
||||||
|
#define CheckSupervisor(x) \
|
||||||
|
if constexpr (InstructionSet::M68k::requires_supervisor<InstructionSet::M68k::Model::M68000>(InstructionSet::M68k::Operation::x)) { \
|
||||||
|
if(!status_.is_supervisor) { \
|
||||||
|
RaiseException(InstructionSet::M68k::Exception::PrivilegeViolation); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
#define CASE(x) \
|
#define CASE(x) \
|
||||||
case InstructionSet::M68k::Operation::x: \
|
case InstructionSet::M68k::Operation::x: \
|
||||||
|
CheckSupervisor(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) \
|
#define StdCASE(x, y) \
|
||||||
@ -638,11 +634,13 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
InstructionSet::M68k::operand_flags<InstructionSet::M68k::Model::M68000, InstructionSet::M68k::Operation::x>() == \
|
InstructionSet::M68k::operand_flags<InstructionSet::M68k::Model::M68000, InstructionSet::M68k::Operation::x>() == \
|
||||||
InstructionSet::M68k::operand_flags<InstructionSet::M68k::Model::M68000, InstructionSet::M68k::Operation::y>() && \
|
InstructionSet::M68k::operand_flags<InstructionSet::M68k::Model::M68000, InstructionSet::M68k::Operation::y>() && \
|
||||||
InstructionSet::M68k::operand_size<InstructionSet::M68k::Operation::x>() == \
|
InstructionSet::M68k::operand_size<InstructionSet::M68k::Operation::x>() == \
|
||||||
InstructionSet::M68k::operand_size<InstructionSet::M68k::Operation::y>() \
|
InstructionSet::M68k::operand_size<InstructionSet::M68k::Operation::y>() && \
|
||||||
|
InstructionSet::M68k::requires_supervisor<InstructionSet::M68k::Model::M68000>(InstructionSet::M68k::Operation::x) == \
|
||||||
|
InstructionSet::M68k::requires_supervisor<InstructionSet::M68k::Model::M68000>(InstructionSet::M68k::Operation::y) \
|
||||||
); \
|
); \
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
|
|
||||||
#define SpecialCASE(x) case InstructionSet::M68k::Operation::x: MoveToStateSpecific(x)
|
#define SpecialCASE(x) case InstructionSet::M68k::Operation::x: CheckSupervisor(x); MoveToStateSpecific(x)
|
||||||
|
|
||||||
switch(instruction_.operation) {
|
switch(instruction_.operation) {
|
||||||
case InstructionSet::M68k::Operation::Undefined:
|
case InstructionSet::M68k::Operation::Undefined:
|
||||||
@ -698,7 +696,9 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
|
|
||||||
StdCASE(CMPb, perform_state_ = Perform_np);
|
StdCASE(CMPb, perform_state_ = Perform_np);
|
||||||
StdCASE(CMPw, perform_state_ = Perform_np);
|
StdCASE(CMPw, perform_state_ = Perform_np);
|
||||||
StdCASE(CMPl, perform_state_ = Perform_np_n);
|
StdCASE(CMPl,
|
||||||
|
perform_state_ = instruction_.mode(1) == Mode::DataRegisterDirect ? Perform_np_n : Perform_np
|
||||||
|
);
|
||||||
|
|
||||||
StdCASE(CMPAw, perform_state_ = Perform_np_n);
|
StdCASE(CMPAw, perform_state_ = Perform_np_n);
|
||||||
StdCASE(CMPAl, perform_state_ = Perform_np_n);
|
StdCASE(CMPAl, perform_state_ = Perform_np_n);
|
||||||
@ -747,6 +747,12 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
Duplicate(SUBb, ADDb) StdCASE(ADDb, perform_state_ = Perform_np)
|
Duplicate(SUBb, ADDb) StdCASE(ADDb, perform_state_ = Perform_np)
|
||||||
Duplicate(SUBw, ADDw) StdCASE(ADDw, perform_state_ = Perform_np)
|
Duplicate(SUBw, ADDw) StdCASE(ADDw, perform_state_ = Perform_np)
|
||||||
Duplicate(SUBl, ADDl) StdCASE(ADDl, {
|
Duplicate(SUBl, ADDl) StdCASE(ADDl, {
|
||||||
|
if(instruction_.mode(0) == Mode::Quick) {
|
||||||
|
perform_state_ = (
|
||||||
|
instruction_.mode(1) == Mode::AddressRegisterDirect ||
|
||||||
|
instruction_.mode(1) == Mode::DataRegisterDirect
|
||||||
|
) ? Perform_np_nn : Perform_np;
|
||||||
|
} else {
|
||||||
if(instruction_.mode(1) != Mode::DataRegisterDirect) {
|
if(instruction_.mode(1) != Mode::DataRegisterDirect) {
|
||||||
perform_state_ = Perform_np;
|
perform_state_ = Perform_np;
|
||||||
} else {
|
} else {
|
||||||
@ -761,6 +767,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Duplicate(SUBAw, ADDAw) StdCASE(ADDAw, perform_state_ = Perform_np_nn)
|
Duplicate(SUBAw, ADDAw) StdCASE(ADDAw, perform_state_ = Perform_np_nn)
|
||||||
@ -922,11 +929,11 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
|
|
||||||
StdCASE(LEA, {
|
StdCASE(LEA, {
|
||||||
post_ea_state_ = LEA;
|
post_ea_state_ = LEA;
|
||||||
MoveToStateSpecific(CalcEffectiveAddress);
|
MoveToStateSpecific(CalcEffectiveAddressIdleFor8bitDisplacement);
|
||||||
});
|
});
|
||||||
StdCASE(PEA, {
|
StdCASE(PEA, {
|
||||||
post_ea_state_ = PEA;
|
post_ea_state_ = PEA;
|
||||||
MoveToStateSpecific(CalcEffectiveAddress);
|
MoveToStateSpecific(CalcEffectiveAddressIdleFor8bitDisplacement);
|
||||||
});
|
});
|
||||||
|
|
||||||
StdCASE(TAS, {
|
StdCASE(TAS, {
|
||||||
@ -936,13 +943,13 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
// for the other cases.
|
// for the other cases.
|
||||||
if(instruction_.mode(0) != Mode::DataRegisterDirect) {
|
if(instruction_.mode(0) != Mode::DataRegisterDirect) {
|
||||||
post_ea_state_ = TAS;
|
post_ea_state_ = TAS;
|
||||||
MoveToStateSpecific(CalcEffectiveAddress);
|
MoveToStateSpecific(CalcEffectiveAddressIdleFor8bitDisplacement);
|
||||||
}
|
}
|
||||||
|
|
||||||
perform_state_ = Perform_np;
|
perform_state_ = Perform_np;
|
||||||
});
|
});
|
||||||
|
|
||||||
Duplicate(MOVEtoCCR, MOVEtoSR);
|
StdCASE(MOVEtoCCR, perform_state_ = MOVEtoCCRSR);
|
||||||
StdCASE(MOVEtoSR, perform_state_ = MOVEtoCCRSR);
|
StdCASE(MOVEtoSR, perform_state_ = MOVEtoCCRSR);
|
||||||
StdCASE(MOVEfromSR, {
|
StdCASE(MOVEfromSR, {
|
||||||
if(instruction_.mode(0) == Mode::DataRegisterDirect) {
|
if(instruction_.mode(0) == Mode::DataRegisterDirect) {
|
||||||
@ -994,6 +1001,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
#undef StdCASE
|
#undef StdCASE
|
||||||
#undef CASE
|
#undef CASE
|
||||||
#undef SpecialCASE
|
#undef SpecialCASE
|
||||||
|
#undef CheckSupervisor
|
||||||
|
|
||||||
// MARK: - Fetch, dispatch.
|
// MARK: - Fetch, dispatch.
|
||||||
|
|
||||||
@ -1098,6 +1106,17 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
BeginState(CalcEffectiveAddressIdleFor8bitDisplacement):
|
||||||
|
if(
|
||||||
|
instruction_.mode(next_operand_) != Mode::AddressRegisterIndirectWithIndex8bitDisplacement &&
|
||||||
|
instruction_.mode(next_operand_) != Mode::ProgramCounterIndirectWithIndex8bitDisplacement
|
||||||
|
) {
|
||||||
|
MoveToStateSpecific(CalcEffectiveAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
IdleBus(1);
|
||||||
|
[[fallthrough]];
|
||||||
|
|
||||||
BeginState(CalcEffectiveAddress):
|
BeginState(CalcEffectiveAddress):
|
||||||
switch(instruction_.mode(next_operand_)) {
|
switch(instruction_.mode(next_operand_)) {
|
||||||
default:
|
default:
|
||||||
@ -1323,7 +1342,6 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
|
|
||||||
BeginState(CalcAddressRegisterIndirectWithIndex8bitDisplacement):
|
BeginState(CalcAddressRegisterIndirectWithIndex8bitDisplacement):
|
||||||
effective_address_[next_operand_].l = d8Xn(registers_[8 + instruction_.reg(next_operand_)].l);
|
effective_address_[next_operand_].l = d8Xn(registers_[8 + instruction_.reg(next_operand_)].l);
|
||||||
IdleBus(1); // n
|
|
||||||
Prefetch(); // np
|
Prefetch(); // np
|
||||||
IdleBus(1); // n
|
IdleBus(1); // n
|
||||||
MoveToStateDynamic(post_ea_state_);
|
MoveToStateDynamic(post_ea_state_);
|
||||||
@ -1359,7 +1377,6 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
|
|
||||||
BeginState(CalcProgramCounterIndirectWithIndex8bitDisplacement):
|
BeginState(CalcProgramCounterIndirectWithIndex8bitDisplacement):
|
||||||
effective_address_[next_operand_].l = d8Xn(program_counter_.l - 2);
|
effective_address_[next_operand_].l = d8Xn(program_counter_.l - 2);
|
||||||
IdleBus(1); // n
|
|
||||||
Prefetch(); // np
|
Prefetch(); // np
|
||||||
IdleBus(1); // n
|
IdleBus(1); // n
|
||||||
MoveToStateDynamic(post_ea_state_);
|
MoveToStateDynamic(post_ea_state_);
|
||||||
|
Loading…
Reference in New Issue
Block a user