Skip to content

Commit

Permalink
arm7tdmi, gba: more IRQ timing improvements (#1707)
Browse files Browse the repository at this point in the history
- Check CPSR interrupt disable bit during decode stage
- Only update IRQ line at the start of memory accesses or idle cycles
  • Loading branch information
png183 authored Dec 2, 2024
1 parent 3bd385e commit 7cc6d51
Show file tree
Hide file tree
Showing 6 changed files with 11 additions and 5 deletions.
1 change: 1 addition & 0 deletions ares/component/processor/arm7tdmi/arm7tdmi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ struct ARM7TDMI {
n32 address;
n32 instruction;
b1 thumb; //not used by fetch stage
b1 irq; //not used by fetch stage
};

n1 reload = 1;
Expand Down
6 changes: 3 additions & 3 deletions ares/component/processor/arm7tdmi/instruction.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
auto ARM7TDMI::fetch() -> void {
pipeline.execute = pipeline.decode;
pipeline.execute.irq = pipeline.execute.irq & irq;
pipeline.decode = pipeline.fetch;
pipeline.decode.thumb = cpsr().t;
pipeline.decode.irq = !cpsr().i;

u32 sequential = Sequential;
if(pipeline.nonsequential) {
Expand All @@ -28,11 +30,9 @@ auto ARM7TDMI::instruction() -> void {
pipeline.fetch.instruction = read(Prefetch | size | Nonsequential, pipeline.fetch.address);
fetch();
}

n1 irqRaised = irq;
fetch();

if(irqRaised && !cpsr().i) {
if(pipeline.execute.irq) {
exception(PSR::IRQ, 0x18);
if(pipeline.execute.thumb) r(14).data += 2;
return;
Expand Down
3 changes: 3 additions & 0 deletions ares/component/processor/arm7tdmi/serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,13 @@ auto ARM7TDMI::Pipeline::serialize(serializer& s) -> void {
s(fetch.address);
s(fetch.instruction);
s(fetch.thumb);
s(fetch.irq);
s(decode.address);
s(decode.instruction);
s(decode.thumb);
s(decode.irq);
s(execute.address);
s(execute.instruction);
s(execute.thumb);
s(execute.irq);
}
3 changes: 3 additions & 0 deletions ares/gba/cpu/bus.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
auto CPU::sleep() -> void {
dmaRun();
ARM7TDMI::irq = irq.synchronizer;
prefetchStep(1);
}

Expand Down Expand Up @@ -44,6 +45,7 @@ inline auto CPU::getBus(u32 mode, n32 address) -> n32 {

auto CPU::get(u32 mode, n32 address) -> n32 {
dmaRun();
ARM7TDMI::irq = irq.synchronizer;
return getBus<false>(mode, address);
}

Expand All @@ -53,6 +55,7 @@ auto CPU::getDebugger(u32 mode, n32 address) -> n32 {

auto CPU::set(u32 mode, n32 address, n32 word) -> void {
dmaRun();
ARM7TDMI::irq = irq.synchronizer;
u32 clocks = _wait(mode, address);

if(address >= 0x1000'0000) {
Expand Down
1 change: 0 additions & 1 deletion ares/gba/cpu/cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ auto CPU::setInterruptFlag(u32 source) -> void {
}

inline auto CPU::stepIRQ() -> void {
ARM7TDMI::irq = irq.synchronizer;
irq.synchronizer = irq.ime[0] && (irq.enable[0] & irq.flag[0]);
irq.enable[0] = irq.enable[1];
irq.flag[0] = irq.flag[1];
Expand Down
2 changes: 1 addition & 1 deletion ares/gba/system/serialization.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
static const string SerializerVersion = "v141.2";
static const string SerializerVersion = "v141.3";

auto System::serialize(bool synchronize) -> serializer {
if(synchronize) scheduler.enter(Scheduler::Mode::Synchronize);
Expand Down

0 comments on commit 7cc6d51

Please sign in to comment.