diff --git a/OSBindings/Mac/Clock SignalTests/68000Tests.mm b/OSBindings/Mac/Clock SignalTests/68000Tests.mm index bd069d7c7..a192a05fe 100644 --- a/OSBindings/Mac/Clock SignalTests/68000Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/68000Tests.mm @@ -223,8 +223,42 @@ class CPU::MC68000::ProcessorStorageTests { _machine->run_for_instructions(1); 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 - // by the wonders of prefetch the program counter is now at 1008. + 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. +} + +- (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 { diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index b287c398b..e3b61d156 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -41,7 +41,8 @@ ((active_step_->microcycle.operation & Microcycle::IsProgram) ? 0x02 : 0x01) | \ (is_supervisor_ << 2) | \ (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)) @@ -100,8 +101,9 @@ template void Proces const auto offending_address = *active_step_->microcycle.address; active_program_ = nullptr; 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); + program_counter_.full -= 4; + active_step_ = &all_bus_steps_[active_micro_op_->bus_program]; } } @@ -114,8 +116,16 @@ template void Proces const auto offending_address = *active_step_->microcycle.address; active_program_ = nullptr; 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); + 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 diff --git a/Processors/68000/Implementation/68000Storage.cpp b/Processors/68000/Implementation/68000Storage.cpp index 1bbd45d7f..00532fd84 100644 --- a/Processors/68000/Implementation/68000Storage.cpp +++ b/Processors/68000/Implementation/68000Storage.cpp @@ -3262,9 +3262,9 @@ CPU::MC68000::ProcessorStorage::ProcessorStorage() { &destination_bus_data_[0].halves.low, &program_counter_.halves.high, &decoded_instruction_, - &effective_address_[0].halves.low, + &effective_address_[1].halves.low, &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.