mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-03 08:05:40 +00:00
Merge pull request #718 from TomHarte/BusErrorStack
Adds a test and fixes for the bus error stack frame.
This commit is contained in:
commit
b3f806201b
@ -223,10 +223,44 @@ class CPU::MC68000::ProcessorStorageTests {
|
|||||||
_machine->run_for_instructions(1);
|
_machine->run_for_instructions(1);
|
||||||
|
|
||||||
const auto state = _machine->processor().get_state();
|
const auto state = _machine->processor().get_state();
|
||||||
XCTAssert(state.program_counter == 0x1008); // i.e. the interrupt happened, the instruction performed was the one at 1004, and therefore
|
XCTAssertEqual(state.program_counter, 0x1008); // i.e. the interrupt happened, the instruction performed was the one at 1004, and therefore
|
||||||
// by the wonders of prefetch the program counter is now at 1008.
|
// by the wonders of prefetch the program counter is now at 1008.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)testAddressErrorStack {
|
||||||
|
// Cause an address error.
|
||||||
|
_machine->set_program({
|
||||||
|
0x3c7c, 0x2001, // MOVEA.w #$2001, A6
|
||||||
|
0x4a9e, // TST (A6)+
|
||||||
|
});
|
||||||
|
_machine->run_for_instructions(2);
|
||||||
|
|
||||||
|
// Check what was left on the stack for appropriate fields.
|
||||||
|
const auto stack_frame = _machine->ram_at(0x1f8);
|
||||||
|
|
||||||
|
// Function code et al.
|
||||||
|
XCTAssertEqual(stack_frame[0],
|
||||||
|
(0x4a9e & 0xffe0) | // Top 11 bits: decoded instruction;
|
||||||
|
0x10 | // Bit 4: read or write;
|
||||||
|
0x0 | // Bit 3: 0 = in instruction, 1 = not;
|
||||||
|
0x5 // Bits 0–2: FC0–2, i.e. bit 2 = supervisor, bit 1 = is program, bit 0 = is data.
|
||||||
|
);
|
||||||
|
|
||||||
|
// Access address.
|
||||||
|
XCTAssertEqual(stack_frame[1], 0x0000);
|
||||||
|
XCTAssertEqual(stack_frame[2], 0x2001);
|
||||||
|
|
||||||
|
// Instruction.
|
||||||
|
XCTAssertEqual(stack_frame[3], 0x4a9e);
|
||||||
|
|
||||||
|
// Status.
|
||||||
|
XCTAssertEqual(stack_frame[4], 0x2700);
|
||||||
|
|
||||||
|
// PC.
|
||||||
|
XCTAssertEqual(stack_frame[5], 0x0000);
|
||||||
|
XCTAssertEqual(stack_frame[6], 0x1004);
|
||||||
|
}
|
||||||
|
|
||||||
- (void)testOpcodeCoverage {
|
- (void)testOpcodeCoverage {
|
||||||
// Perform an audit of implemented instructions.
|
// Perform an audit of implemented instructions.
|
||||||
CPU::MC68000::ProcessorStorageTests storage_tests(
|
CPU::MC68000::ProcessorStorageTests storage_tests(
|
||||||
|
@ -41,7 +41,8 @@
|
|||||||
((active_step_->microcycle.operation & Microcycle::IsProgram) ? 0x02 : 0x01) | \
|
((active_step_->microcycle.operation & Microcycle::IsProgram) ? 0x02 : 0x01) | \
|
||||||
(is_supervisor_ << 2) | \
|
(is_supervisor_ << 2) | \
|
||||||
(active_program_ ? 0x08 : 0) | \
|
(active_program_ ? 0x08 : 0) | \
|
||||||
((active_step_->microcycle.operation & Microcycle::Read) ? 0x10 : 0) \
|
((active_step_->microcycle.operation & Microcycle::Read) ? 0x10 : 0) | \
|
||||||
|
(decoded_instruction_.full & 0xffe0) \
|
||||||
)
|
)
|
||||||
|
|
||||||
#define u_extend16(x) uint32_t(int16_t(x))
|
#define u_extend16(x) uint32_t(int16_t(x))
|
||||||
@ -100,8 +101,9 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
|
|||||||
const auto offending_address = *active_step_->microcycle.address;
|
const auto offending_address = *active_step_->microcycle.address;
|
||||||
active_program_ = nullptr;
|
active_program_ = nullptr;
|
||||||
active_micro_op_ = long_exception_micro_ops_;
|
active_micro_op_ = long_exception_micro_ops_;
|
||||||
active_step_ = &all_bus_steps_[active_micro_op_->bus_program];
|
|
||||||
populate_bus_error_steps(2, get_status(), get_bus_code(), offending_address);
|
populate_bus_error_steps(2, get_status(), get_bus_code(), offending_address);
|
||||||
|
program_counter_.full -= 4;
|
||||||
|
active_step_ = &all_bus_steps_[active_micro_op_->bus_program];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,8 +116,16 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
|
|||||||
const auto offending_address = *active_step_->microcycle.address;
|
const auto offending_address = *active_step_->microcycle.address;
|
||||||
active_program_ = nullptr;
|
active_program_ = nullptr;
|
||||||
active_micro_op_ = long_exception_micro_ops_;
|
active_micro_op_ = long_exception_micro_ops_;
|
||||||
active_step_ = &all_bus_steps_[active_micro_op_->bus_program];
|
|
||||||
populate_bus_error_steps(3, get_status(), get_bus_code(), offending_address);
|
populate_bus_error_steps(3, get_status(), get_bus_code(), offending_address);
|
||||||
|
program_counter_.full -= 4;
|
||||||
|
active_step_ = &all_bus_steps_[active_micro_op_->bus_program];
|
||||||
|
|
||||||
|
// TODO: the above is only correct prior to the final microcycle of an
|
||||||
|
// instruction. If an exception occurs in the final microcycle then
|
||||||
|
// the next instruction will already have moved into the current instruction
|
||||||
|
// slot (decoded_instruction_ in my terms).
|
||||||
|
|
||||||
|
// TODO: it's also not correct for a bus error that occurs during another exception.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform the microcycle if it is of non-zero length. If this is an operation that
|
// Perform the microcycle if it is of non-zero length. If this is an operation that
|
||||||
|
@ -3262,9 +3262,9 @@ CPU::MC68000::ProcessorStorage::ProcessorStorage() {
|
|||||||
&destination_bus_data_[0].halves.low,
|
&destination_bus_data_[0].halves.low,
|
||||||
&program_counter_.halves.high,
|
&program_counter_.halves.high,
|
||||||
&decoded_instruction_,
|
&decoded_instruction_,
|
||||||
&effective_address_[0].halves.low,
|
&effective_address_[1].halves.low,
|
||||||
&destination_bus_data_[0].halves.high,
|
&destination_bus_data_[0].halves.high,
|
||||||
&effective_address_[0].halves.high
|
&effective_address_[1].halves.high
|
||||||
});
|
});
|
||||||
|
|
||||||
// Also relink the RTE and RTR bus steps to collect the program counter.
|
// Also relink the RTE and RTR bus steps to collect the program counter.
|
||||||
|
Loading…
Reference in New Issue
Block a user