From 1f1ff763e661bab664151c4821c65dad35777976 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 23 Jan 2010 23:36:58 +0000 Subject: [PATCH] 32x: improve irq handling + few bugfixes git-svn-id: file:///home/notaz/opt/svn/PicoDrive@866 be3aeb3a-fb24-0410-a615-afba39da0efa --- cpu/sh2/compiler.c | 1 - cpu/sh2/mame/sh2pico.c | 18 +++++++++--------- cpu/sh2/sh2.c | 20 ++++++++++++++------ cpu/sh2/sh2.h | 2 +- pico/32x/32x.c | 10 +++++----- pico/32x/memory.c | 12 ++++++------ pico/32x/pwm.c | 8 ++++---- pico/pico.c | 4 +--- pico/pico_int.h | 4 ++-- platform/gp2x/version.h | 2 +- 10 files changed, 43 insertions(+), 38 deletions(-) diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 7f0ba660..9861a859 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -17,7 +17,6 @@ * - some constant propagation * * TODO: - * - proper SMC handling * - better constant propagation * - stack caching? * - bug fixing diff --git a/cpu/sh2/mame/sh2pico.c b/cpu/sh2/mame/sh2pico.c index a65638b4..233e0a1f 100644 --- a/cpu/sh2/mame/sh2pico.c +++ b/cpu/sh2/mame/sh2pico.c @@ -74,15 +74,6 @@ void sh2_execute(SH2 *sh2_, int cycles) { UINT32 opcode; - /* FIXME: Darxide doesn't like this */ - if (sh2->test_irq && !sh2->delay && sh2->pending_level > ((sh2->sr >> 4) & 0x0f)) - { - int level = sh2->pending_level; - int vector = sh2->irq_callback(sh2, level); - sh2_do_irq(sh2, level, vector); - sh2->test_irq = 0; - } - if (sh2->delay) { sh2->ppc = sh2->delay; @@ -119,6 +110,15 @@ void sh2_execute(SH2 *sh2_, int cycles) } sh2->icount--; + + if (sh2->test_irq && !sh2->delay && sh2->pending_level > ((sh2->sr >> 4) & 0x0f)) + { + int level = sh2->pending_level; + int vector = sh2->irq_callback(sh2, level); + sh2_do_irq(sh2, level, vector); + sh2->test_irq = 0; + } + } while (sh2->icount > 0 || sh2->delay); /* can't interrupt before delay */ diff --git a/cpu/sh2/sh2.c b/cpu/sh2/sh2.c index a873d183..80c458fc 100644 --- a/cpu/sh2/sh2.c +++ b/cpu/sh2/sh2.c @@ -54,15 +54,23 @@ void sh2_do_irq(SH2 *sh2, int level, int vector) // sh2->icount -= 13; } -void sh2_irl_irq(SH2 *sh2, int level) +void sh2_irl_irq(SH2 *sh2, int level, int nested_call) { sh2->pending_irl = level; - if (level > sh2->pending_int_irq) - sh2->pending_level = level; - else - sh2->pending_level = sh2->pending_int_irq; + if (level < sh2->pending_int_irq) + level = sh2->pending_int_irq; + sh2->pending_level = level; - sh2->test_irq = 1; + if (!nested_call) { + // not in memhandler, so handle this now (recompiler friendly) + // do this to avoid missing irqs that other SH2 might clear + if (level > ((sh2->sr >> 4) & 0x0f)) { + int vector = sh2->irq_callback(sh2, level); + sh2_do_irq(sh2, level, vector); + } + } + else + sh2->test_irq = 1; } void sh2_internal_irq(SH2 *sh2, int level, int vector) diff --git a/cpu/sh2/sh2.h b/cpu/sh2/sh2.h index a91a597e..a69a159d 100644 --- a/cpu/sh2/sh2.h +++ b/cpu/sh2/sh2.h @@ -61,7 +61,7 @@ extern SH2 *sh2; // active sh2. XXX: consider removing int sh2_init(SH2 *sh2, int is_slave); void sh2_finish(SH2 *sh2); void sh2_reset(SH2 *sh2); -void sh2_irl_irq(SH2 *sh2, int level); +void sh2_irl_irq(SH2 *sh2, int level, int nested_call); void sh2_internal_irq(SH2 *sh2, int level, int vector); void sh2_do_irq(SH2 *sh2, int level, int vector); diff --git a/pico/32x/32x.c b/pico/32x/32x.c index f9ac533d..e7779b9f 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -19,7 +19,7 @@ static int REGPARM(2) sh2_irq_cb(SH2 *sh2, int level) } } -void p32x_update_irls(void) +void p32x_update_irls(int nested_call) { int irqs, mlvl = 0, slvl = 0; @@ -36,8 +36,8 @@ void p32x_update_irls(void) slvl *= 2; elprintf(EL_32X, "update_irls: m %d, s %d", mlvl, slvl); - sh2_irl_irq(&msh2, mlvl); - sh2_irl_irq(&ssh2, slvl); + sh2_irl_irq(&msh2, mlvl, nested_call); + sh2_irl_irq(&ssh2, slvl, nested_call); mlvl = mlvl ? 1 : 0; slvl = slvl ? 1 : 0; p32x_poll_event(mlvl | (slvl << 1), 0); @@ -141,7 +141,7 @@ void PicoReset32x(void) { if (PicoAHW & PAHW_32X) { Pico32x.sh2irqs |= P32XI_VRES; - p32x_update_irls(); + p32x_update_irls(0); p32x_poll_event(3, 0); } } @@ -186,7 +186,7 @@ static void p32x_start_blank(void) } Pico32x.sh2irqs |= P32XI_VINT; - p32x_update_irls(); + p32x_update_irls(0); p32x_poll_event(3, 1); } diff --git a/pico/32x/memory.c b/pico/32x/memory.c index a958737c..ee33caa9 100644 --- a/pico/32x/memory.c +++ b/pico/32x/memory.c @@ -224,12 +224,12 @@ static void p32x_reg_write8(u32 a, u32 d) case 3: // irq ctl if ((d & 1) && !(Pico32x.sh2irqi[0] & P32XI_CMD)) { Pico32x.sh2irqi[0] |= P32XI_CMD; - p32x_update_irls(); + p32x_update_irls(0); SekEndRun(16); } if ((d & 2) && !(Pico32x.sh2irqi[1] & P32XI_CMD)) { Pico32x.sh2irqi[1] |= P32XI_CMD; - p32x_update_irls(); + p32x_update_irls(0); SekEndRun(16); } return; @@ -431,7 +431,7 @@ static void p32x_sh2reg_write8(u32 a, u32 d, int cpuid) Pico32x.sh2irq_mask[cpuid] = d & 0x8f; Pico32x.sh2_regs[0] &= ~0x80; Pico32x.sh2_regs[0] |= d & 0x80; - p32x_update_irls(); + p32x_update_irls(1); return; case 5: // H count Pico32x.sh2_regs[4 / 2] = d & 0xff; @@ -486,7 +486,7 @@ static void p32x_sh2reg_write16(u32 a, u32 d, int cpuid) return; irls: - p32x_update_irls(); + p32x_update_irls(1); } // ------------------------------------------------------------------ @@ -950,7 +950,7 @@ static u32 sh2_read8_cs0(u32 a, int id) if (id == 1 && a < sizeof(Pico32xMem->sh2_rom_s)) return Pico32xMem->sh2_rom_s[a ^ 1]; - if ((a & 0x3ff00) == 0x4200) { + if ((a & 0x3fe00) == 0x4200) { d = Pico32xMem->pal[(a & 0x1ff) / 2]; goto out_16to8; } @@ -1004,7 +1004,7 @@ static u32 sh2_read16_cs0(u32 a, int id) if (id == 1 && a < sizeof(Pico32xMem->sh2_rom_s)) return *(u16 *)(Pico32xMem->sh2_rom_s + a); - if ((a & 0x3ff00) == 0x4200) { + if ((a & 0x3fe00) == 0x4200) { d = Pico32xMem->pal[(a & 0x1ff) / 2]; goto out; } diff --git a/pico/32x/pwm.c b/pico/32x/pwm.c index 64d67223..8e365892 100644 --- a/pico/32x/pwm.c +++ b/pico/32x/pwm.c @@ -47,7 +47,7 @@ void p32x_timers_recalc(void) } // PWM irq for every tm samples -void p32x_timers_do(int new_line) +void p32x_timers_do(int line_call) { int tm, cnt, i; @@ -55,17 +55,17 @@ void p32x_timers_do(int new_line) { tm = (Pico32x.regs[0x30 / 2] & 0x0f00) >> 8; if (tm != 0) { - if (new_line) + if (line_call) Pico32x.pwm_irq_sample_cnt += pwm_line_samples; if (Pico32x.pwm_irq_sample_cnt >= (tm << 16)) { Pico32x.pwm_irq_sample_cnt -= tm << 16; Pico32x.sh2irqs |= P32XI_PWM; - p32x_update_irls(); + p32x_update_irls(!line_call); } } } - if (!new_line) + if (!line_call) return; for (i = 0; i < 2; i++) { diff --git a/pico/pico.c b/pico/pico.c index c63360c6..22f45a33 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -192,10 +192,8 @@ int PicoReset(void) if (!(PicoOpt & POPT_DIS_IDLE_DET)) SekInitIdleDet(); - if (PicoOpt & POPT_EN_32X) { + if (PicoOpt & POPT_EN_32X) PicoReset32x(); - return 0; - } // reset sram state; enable sram access by default if it doesn't overlap with ROM Pico.m.sram_reg = 0; diff --git a/pico/pico_int.h b/pico/pico_int.h index bb400863..3ee4ea13 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -706,7 +706,7 @@ void PicoReset32x(void); void Pico32xStartup(void); void PicoUnload32x(void); void PicoFrame32x(void); -void p32x_update_irls(void); +void p32x_update_irls(int nested_call); void p32x_reset_sh2s(void); // 32x/memory.c @@ -734,7 +734,7 @@ extern int Pico32xDrawMode; unsigned int p32x_pwm_read16(unsigned int a); void p32x_pwm_write16(unsigned int a, unsigned int d); void p32x_pwm_update(int *buf32, int length, int stereo); -void p32x_timers_do(int new_line); +void p32x_timers_do(int line_call); void p32x_timers_recalc(void); extern int pwm_frame_smp_cnt; diff --git a/platform/gp2x/version.h b/platform/gp2x/version.h index 1fddda52..8028c0d1 100644 --- a/platform/gp2x/version.h +++ b/platform/gp2x/version.h @@ -1,2 +1,2 @@ -#define VERSION "1.70b2" +#define VERSION "1.70b3" -- 2.39.5