From 6641f75ffb17887e95b89ff1ca9e8ba63ea66349 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Mon, 12 Dec 2022 15:49:25 -0800 Subject: [PATCH] Add external interrupt tests --- Source/DSPSpy/dsp_interface.h | 2 + Source/DSPSpy/main_spy.cpp | 32 +++++++ Source/DSPSpy/real_dsp.cpp | 13 +++ Source/DSPSpy/real_dsp.h | 10 ++- Source/DSPSpy/tests/external_interrupt.ds | 57 +++++++++++++ .../DSPSpy/tests/external_interrupt_delay.ds | 55 ++++++++++++ .../DSPSpy/tests/external_interrupt_nested.ds | 77 +++++++++++++++++ .../tests/external_interrupt_no_delay.ds | 57 +++++++++++++ ...nal_interrupt_other_interrupt_on_return.ds | 85 +++++++++++++++++++ .../DSPSpy/tests/external_interrupt_toggle.ds | 61 +++++++++++++ .../tests/external_interrupt_toggle_2.ds | 64 ++++++++++++++ 11 files changed, 509 insertions(+), 4 deletions(-) create mode 100644 Source/DSPSpy/tests/external_interrupt.ds create mode 100644 Source/DSPSpy/tests/external_interrupt_delay.ds create mode 100644 Source/DSPSpy/tests/external_interrupt_nested.ds create mode 100644 Source/DSPSpy/tests/external_interrupt_no_delay.ds create mode 100644 Source/DSPSpy/tests/external_interrupt_other_interrupt_on_return.ds create mode 100644 Source/DSPSpy/tests/external_interrupt_toggle.ds create mode 100644 Source/DSPSpy/tests/external_interrupt_toggle_2.ds diff --git a/Source/DSPSpy/dsp_interface.h b/Source/DSPSpy/dsp_interface.h index 7a4c812d96..34ef05cba0 100644 --- a/Source/DSPSpy/dsp_interface.h +++ b/Source/DSPSpy/dsp_interface.h @@ -26,6 +26,8 @@ public: virtual void Reset() = 0; virtual u32 CheckMailTo() = 0; virtual void SendMailTo(u32 mail) = 0; + virtual void SetInterrupt() = 0; + virtual bool CheckInterrupt() = 0; // Yeah, yeah, having a method here makes this not a pure interface - but // the implementation does nothing but calling the virtual methods above. diff --git a/Source/DSPSpy/main_spy.cpp b/Source/DSPSpy/main_spy.cpp index bfff921e10..492632ba5f 100644 --- a/Source/DSPSpy/main_spy.cpp +++ b/Source/DSPSpy/main_spy.cpp @@ -25,6 +25,9 @@ #include #include +// From libogc's timesupp.c (not in the header :|) +extern "C" u32 gettick(void); + #ifdef _MSC_VER // Just for easy looking :) #define HW_RVL // HW_DOL @@ -420,6 +423,35 @@ void handle_dsp_mail(void) DumpDSP_ROMs(dspbufP, &dspbufP[0x1000]); } + // Request for an interrupt + else if (mail == 0x88881111) + { + if (real_dsp.CheckInterrupt()) + { + CON_PrintRow(4, 25, "Already has interrupt?"); + } + else + { + const u32 now = gettick(); + real_dsp.SetInterrupt(); + u32 end = gettick(); + u32 tries = 0; + while (real_dsp.CheckInterrupt() && end - now < 1000000) + { + end = gettick(); + tries++; + } + if (end - now < 1000000) + { + CON_PrintRow(4, 25, "Interrupt after %d ticks / %d tries", end - now, tries); + } + else + { + CON_PrintRow(4, 25, "No interrupt after %d ticks / %d tries", end - now, tries); + } + } + } + // SDK status mails /* // GBA ucode diff --git a/Source/DSPSpy/real_dsp.cpp b/Source/DSPSpy/real_dsp.cpp index 5921821b08..63fb50b407 100644 --- a/Source/DSPSpy/real_dsp.cpp +++ b/Source/DSPSpy/real_dsp.cpp @@ -51,3 +51,16 @@ void RealDSP::SendMailTo(u32 mail) { DSP_SendMailTo(mail); } + +void RealDSP::SetInterrupt() +{ + u32 level; + _CPU_ISR_Disable(level); + _dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT | DSPCR_ARINT | DSPCR_DSPINT)) | DSPCR_PIINT; + _CPU_ISR_Restore(level); +} + +bool RealDSP::CheckInterrupt() +{ + return (_dspReg[5] & DSPCR_PIINT) != 0; +} diff --git a/Source/DSPSpy/real_dsp.h b/Source/DSPSpy/real_dsp.h index 5ce8513be1..069fe81cc4 100644 --- a/Source/DSPSpy/real_dsp.h +++ b/Source/DSPSpy/real_dsp.h @@ -8,8 +8,10 @@ class RealDSP : public IDSP { public: - virtual void Init(); - virtual void Reset(); - virtual u32 CheckMailTo(); - virtual void SendMailTo(u32 mail); + void Init() override; + void Reset() override; + u32 CheckMailTo() override; + void SendMailTo(u32 mail) override; + void SetInterrupt() override; + bool CheckInterrupt() override; }; diff --git a/Source/DSPSpy/tests/external_interrupt.ds b/Source/DSPSpy/tests/external_interrupt.ds new file mode 100644 index 0000000000..df53cc8688 --- /dev/null +++ b/Source/DSPSpy/tests/external_interrupt.ds @@ -0,0 +1,57 @@ +; This test needs to manually specify IRQs + jmp irq0 + jmp irq1 + jmp irq2 + jmp irq3 + jmp irq4 + jmp irq5 + jmp irq6 + jmp external_irq + +incdir "tests" +include "dsp_base_noirq.inc" + +test_main: + CLR $ACC0 + SBCLR #2 + SBCLR #3 + SBCLR #4 + SBCLR #5 + SBCLR #6 + + LRI $AR0, #0 + + LRIS $AX0.H, #1 + CALL send_back + + SI @DMBH, #0x8888 + SI @DMBL, #0x1111 + +wait_cpu_read: + LRS $AC1.M, @DMBH + ANDCF $AC1.M, #0x8000 + JLZ wait_cpu_read + + CLR $ACC1 +second_loop: + INC $ACC1 + CMPIS $AC1.M, #1 + JNZ second_loop + + SBSET #6 + SBSET #5 + LRI $AR0, #2 + LRI $AR0, #3 + LRI $AR0, #4 + LRI $AR0, #5 + LRI $AR0, #6 + + LRIS $AX0.H, #2 + CALL send_back + + JMP end_of_test + +external_irq: + LRIS $AX0.H, #3 + CALL send_back + RTI diff --git a/Source/DSPSpy/tests/external_interrupt_delay.ds b/Source/DSPSpy/tests/external_interrupt_delay.ds new file mode 100644 index 0000000000..9f440273a1 --- /dev/null +++ b/Source/DSPSpy/tests/external_interrupt_delay.ds @@ -0,0 +1,55 @@ +; This test needs to manually specify IRQs + jmp irq0 + jmp irq1 + jmp irq2 + jmp irq3 + jmp irq4 + jmp irq5 + jmp irq6 + jmp external_irq + +incdir "tests" +include "dsp_base_noirq.inc" + +test_main: + CLR $ACC0 + SBCLR #5 + SBCLR #6 + + LRI $AR0, #0 + + LRIS $AX0.H, #1 + CALL send_back + + SI @DMBH, #0x8888 + SI @DMBL, #0x1111 + +wait_cpu_read: + LRS $AC1.M, @DMBH + ANDCF $AC1.M, #0x8000 + JLZ wait_cpu_read + + ; Wait a while (0x10000 increments) + CLR $ACC1 +second_loop: + INC $ACC1 + CMPIS $AC1.M, #1 + JNZ second_loop + + SBSET #6 + SBSET #5 + LRI $AR0, #2 + LRI $AR0, #3 + LRI $AR0, #4 + LRI $AR0, #5 + LRI $AR0, #6 + + LRIS $AX0.H, #2 + CALL send_back + + JMP end_of_test + +external_irq: + LRIS $AX0.H, #3 + CALL send_back + RTI diff --git a/Source/DSPSpy/tests/external_interrupt_nested.ds b/Source/DSPSpy/tests/external_interrupt_nested.ds new file mode 100644 index 0000000000..e0e8a7d15f --- /dev/null +++ b/Source/DSPSpy/tests/external_interrupt_nested.ds @@ -0,0 +1,77 @@ +; This test needs to manually specify IRQs + jmp irq0 + jmp irq1 + jmp irq2 + jmp irq3 + jmp irq4 + jmp irq5 + jmp irq6 + jmp external_irq + +incdir "tests" +include "dsp_base_noirq.inc" + +test_main: + CLR $ACC0 + SBCLR #2 + SBCLR #3 + SBCLR #4 + SBCLR #5 + SBCLR #6 + + LRI $AR0, #0 + + LRIS $AX0.H, #1 + CALL send_back + + SI @DMBH, #0x8888 + SI @DMBL, #0x1111 + +wait_cpu_read: + LRS $AC1.M, @DMBH + ANDCF $AC1.M, #0x8000 + JLZ wait_cpu_read + + CLR $ACC1 +second_loop: + INC $ACC1 + CMPIS $AC1.M, #1 + JNZ second_loop + + SBSET #6 + SBSET #5 + LRI $AR0, #2 + LRI $AR0, #3 + LRI $AR0, #4 + LRI $AR0, #5 + LRI $AR0, #6 + + LRIS $AX0.H, #2 + CALL send_back + + JMP end_of_test + +external_irq: + INCM $AC0.M + LRIS $AX0.H, #3 + CALL send_back + + ; Only trigger a nested interrupt the first time through + CMPIS $AC0.M, #1 + RTINZ + + SI @DMBH, #0x8888 + SI @DMBL, #0x1111 + +wait_cpu_read_irq: + LRS $AC1.M, @DMBH + ANDCF $AC1.M, #0x8000 + JLZ wait_cpu_read_irq + + CLR $ACC1 +second_loop_irq: + INC $ACC1 + CMPIS $AC1.M, #1 + JNZ second_loop_irq + + RTI diff --git a/Source/DSPSpy/tests/external_interrupt_no_delay.ds b/Source/DSPSpy/tests/external_interrupt_no_delay.ds new file mode 100644 index 0000000000..549b499fe3 --- /dev/null +++ b/Source/DSPSpy/tests/external_interrupt_no_delay.ds @@ -0,0 +1,57 @@ +; This test needs to manually specify IRQs + jmp irq0 + jmp irq1 + jmp irq2 + jmp irq3 + jmp irq4 + jmp irq5 + jmp irq6 + jmp external_irq + +incdir "tests" +include "dsp_base_noirq.inc" + +test_main: + CLR $ACC0 + SBCLR #5 + SBCLR #6 + + LRI $AR0, #0 + + LRIS $AX0.H, #1 + CALL send_back + + SI @DMBH, #0x8888 + SI @DMBL, #0x1111 + +wait_cpu_read: + LRS $AC1.M, @DMBH + ANDCF $AC1.M, #0x8000 + JLZ wait_cpu_read + + ; Wait a while (0x10000 increments) + CLR $ACC1 + + SBSET #6 + SBSET #5 + +second_loop: + INC $ACC1 + CMPIS $AC1.M, #1 + JNZ second_loop + + LRI $AR0, #2 + LRI $AR0, #3 + LRI $AR0, #4 + LRI $AR0, #5 + LRI $AR0, #6 + + LRIS $AX0.H, #2 + CALL send_back + + JMP end_of_test + +external_irq: + LRIS $AX0.H, #3 + CALL send_back + RTI diff --git a/Source/DSPSpy/tests/external_interrupt_other_interrupt_on_return.ds b/Source/DSPSpy/tests/external_interrupt_other_interrupt_on_return.ds new file mode 100644 index 0000000000..4de8a91ade --- /dev/null +++ b/Source/DSPSpy/tests/external_interrupt_other_interrupt_on_return.ds @@ -0,0 +1,85 @@ +; This test needs to manually specify IRQs + jmp irq0 + jmp irq1 + jmp irq2 + jmp irq3 + jmp irq4 + jmp accov_irq + jmp irq6 + jmp external_irq + +incdir "tests" +include "dsp_base_noirq.inc" + +test_main: + ; Use the accelerator to generate an IRQ by setting the start and end address to 0 + ; This will result in an interrupt on every read + SI @0xffda, #0 ; pred_scale + SI @0xffdb, #0 ; yn1 + SI @0xffdc, #0 ; yn2 + SI @0xffd1, #0 ; SampleFormat + SI @ACSAH, #0 + SI @ACCAH, #0 + SI @ACSAL, #0 + SI @ACCAL, #0 + SI @ACEAH, #0 + SI @ACEAL, #0 + + CLR $ACC0 + SBCLR #2 + SBSET #3 + SBCLR #4 + SBCLR #5 + SBCLR #6 + + LRI $AR0, #0 + + LRIS $AX0.H, #1 + CALL send_back + + SI @DMBH, #0x8888 + SI @DMBL, #0x1111 + +wait_cpu_read: + LRS $AC1.M, @DMBH + ANDCF $AC1.M, #0x8000 + JLZ wait_cpu_read + + CLR $ACC1 +second_loop: + INC $ACC1 + CMPIS $AC1.M, #1 + JNZ second_loop + + SBSET #6 + SBSET #5 + ; Trigger an interrupt at the same time as external interrupts become enabled + LRS $AX0.L, @ARAM + LRI $AR0, #3 + LRI $AR0, #4 + LRI $AR0, #5 + LRI $AR0, #6 + + LRIS $AX0.H, #2 + CALL send_back + + JMP end_of_test + +accov_irq: + INCM $AC0.M + + ; Restore registers, otherwise no new interrupt will be generated + SI @0xffda, #0 ; pred_scale + SI @0xffdb, #0 ; yn1 + SI @0xffdc, #0 ; yn2 + + LRIS $AX0.H, #3 + CALL send_back + + RTI + +external_irq: + INCM $AC0.M + LRIS $AX0.H, #4 + CALL send_back + RTI diff --git a/Source/DSPSpy/tests/external_interrupt_toggle.ds b/Source/DSPSpy/tests/external_interrupt_toggle.ds new file mode 100644 index 0000000000..eec640bb0a --- /dev/null +++ b/Source/DSPSpy/tests/external_interrupt_toggle.ds @@ -0,0 +1,61 @@ +; This test needs to manually specify IRQs + jmp irq0 + jmp irq1 + jmp irq2 + jmp irq3 + jmp irq4 + jmp irq5 + jmp irq6 + jmp external_irq + +incdir "tests" +include "dsp_base_noirq.inc" + +test_main: + CLR $ACC0 + SBCLR #5 + SBCLR #6 + + LRI $AR0, #0 + + LRIS $AX0.H, #1 + CALL send_back + + SI @DMBH, #0x8888 + SI @DMBL, #0x1111 + +wait_cpu_read: + LRS $AC1.M, @DMBH + ANDCF $AC1.M, #0x8000 + JLZ wait_cpu_read + + ; Wait a while (0x10000 increments) + CLR $ACC1 +second_loop: + INC $ACC1 + CMPIS $AC1.M, #1 + JNZ second_loop + + SBSET #6 + SBSET #5 + SBCLR #5 + SBSET #5 + SBCLR #5 + SBSET #5 + SBCLR #5 + SBSET #5 + SBCLR #5 + SBSET #5 + LRI $AR0, #2 + LRI $AR0, #3 + LRI $AR0, #4 + + LRIS $AX0.H, #2 + CALL send_back + + JMP end_of_test + +external_irq: + LRIS $AX0.H, #3 + CALL send_back + RTI diff --git a/Source/DSPSpy/tests/external_interrupt_toggle_2.ds b/Source/DSPSpy/tests/external_interrupt_toggle_2.ds new file mode 100644 index 0000000000..cf91fa73f4 --- /dev/null +++ b/Source/DSPSpy/tests/external_interrupt_toggle_2.ds @@ -0,0 +1,64 @@ +; This test needs to manually specify IRQs + jmp irq0 + jmp irq1 + jmp irq2 + jmp irq3 + jmp irq4 + jmp irq5 + jmp irq6 + jmp external_irq + +incdir "tests" +include "dsp_base_noirq.inc" + +test_main: + CLR $ACC0 + SBCLR #5 + SBCLR #6 + + LRI $AR0, #0 + + LRIS $AX0.H, #1 + CALL send_back + + SI @DMBH, #0x8888 + SI @DMBL, #0x1111 + +wait_cpu_read: + LRS $AC1.M, @DMBH + ANDCF $AC1.M, #0x8000 + JLZ wait_cpu_read + + ; Wait a while (0x10000 increments) + CLR $ACC1 +second_loop: + INC $ACC1 + CMPIS $AC1.M, #1 + JNZ second_loop + + SBSET #6 + SBSET #5 + SBCLR #5 + LRI $AR0, #2 + SBSET #5 + SBCLR #5 + LRI $AR0, #3 + SBSET #5 + SBCLR #5 + LRI $AR0, #4 + SBSET #5 + SBCLR #5 + LRI $AR0, #5 + SBSET #5 + LRI $AR0, #6 + LRI $AR0, #7 + + LRIS $AX0.H, #2 + CALL send_back + + JMP end_of_test + +external_irq: + LRIS $AX0.H, #3 + CALL send_back + RTI