From 9ea3e547eef7918189a699420d34770c494c992e Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 22 Mar 2024 21:42:34 -0400 Subject: [PATCH] Fix IRQ/FIQ return addresses. --- InstructionSets/ARM/Executor.hpp | 4 +++- InstructionSets/ARM/Registers.hpp | 8 ++++---- Machines/Acorn/Archimedes/Archimedes.cpp | 20 +++++++++++++------ .../xcschemes/Clock Signal.xcscheme | 2 +- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/InstructionSets/ARM/Executor.hpp b/InstructionSets/ARM/Executor.hpp index e29aedcb9..ad763bb6b 100644 --- a/InstructionSets/ARM/Executor.hpp +++ b/InstructionSets/ARM/Executor.hpp @@ -402,7 +402,7 @@ struct Executor { // Check whether access is forced ot the user bank; if so then switch // to it now. Also keep track of the original mode to switch back at // the end. - const Mode original_mode = registers_.mode(); + Mode original_mode = registers_.mode(); const bool adopt_user_mode = flags.load_psr() && ( flags.operation() == BlockDataTransferFlags::Operation::STM || @@ -519,6 +519,8 @@ struct Executor { registers_.set_pc(value); if constexpr (flags.load_psr()) { registers_.set_status(value); + original_mode = registers_.mode(); // Avoid switching back to the wrong mode + // in case user registers were exposed. } } } diff --git a/InstructionSets/ARM/Registers.hpp b/InstructionSets/ARM/Registers.hpp index f158a0408..9e0121567 100644 --- a/InstructionSets/ARM/Registers.hpp +++ b/InstructionSets/ARM/Registers.hpp @@ -148,17 +148,17 @@ struct Registers { // // * exceptions occuring during execution of an instruction are taken // to occur after R15 has already been incremented by 4; but - // * exceptions occurring instead of execution of an isntruction are + // * exceptions occurring instead of execution of an instruction are // taken to occur with R15 pointing to an instruction that hasn't begun. // // i.e. in net R15 always refers to the next instruction // that has not yet started. switch(exception) { // "To return normally from FIQ use SUBS PC, R14_fiq, #4". - case Exception::FIQ: return 0; + case Exception::FIQ: return 4; - // "To return normally from IRQ use SUBS PC, R14_fiq, #4". - case Exception::IRQ: return 0; + // "To return normally from IRQ use SUBS PC, R14_irq, #4". + case Exception::IRQ: return 4; // "If a return is required from [address exception traps], use // SUBS PC, R14_svc, #4. This will return to the instruction after diff --git a/Machines/Acorn/Archimedes/Archimedes.cpp b/Machines/Acorn/Archimedes/Archimedes.cpp index a0356b7e8..567ac85c4 100644 --- a/Machines/Acorn/Archimedes/Archimedes.cpp +++ b/Machines/Acorn/Archimedes/Archimedes.cpp @@ -117,6 +117,12 @@ class ConcreteMachine: return; } if(requests & InterruptRequests::IRQ) { +// logger.info().append("[%d] IRQ at %08x prior:[r13:%08x r14:%08x]", +// instr_count, +// executor_.pc(), +// executor_.registers()[13], +// executor_.registers()[14]); + executor_.registers().interrupt(); } } @@ -134,7 +140,7 @@ class ConcreteMachine: return executor_.bus.video().crt().get_scaled_scan_status(); } - std::array pc_history; + std::array pc_history; std::size_t pc_history_ptr = 0; uint32_t instr_count = 0; @@ -158,6 +164,10 @@ class ConcreteMachine: static uint32_t last_pc = 0; static bool log = false; +// if(executor_.pc() == 0x03803400) { +// printf("At %08x; after last PC %08x and %zu ago was %08x\n", executor_.pc(), pc_history[(pc_history_ptr - 2 + pc_history.size()) % pc_history.size()], pc_history.size(), pc_history[pc_history_ptr]); +// } + uint32_t instruction; pc_history[pc_history_ptr] = executor_.pc(); pc_history_ptr = (pc_history_ptr + 1) % pc_history.size(); @@ -172,11 +182,9 @@ class ConcreteMachine: } // TODO: pipeline prefetch? - if(executor_.pc() == 0x03810bd8) { - printf("At %08x; after last PC %08x and %zu ago was %08x\n", executor_.pc(), pc_history[(pc_history_ptr - 2 + pc_history.size()) % pc_history.size()], pc_history.size(), pc_history[pc_history_ptr]); - } - - log = executor_.pc() == 0x03808de0; +// log |= executor_.pc() == 0x3961244; +// log |= instr_count == 72766815; +// log &= executor_.pc() != 0x000000a0; if(log) { InstructionSet::ARM::Disassembler disassembler; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme index 19b54b90e..474fa352e 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme +++ b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme @@ -62,7 +62,7 @@