From 726a10c257d371d6de4aeb52b6493a25264f5547 Mon Sep 17 00:00:00 2001 From: Patrice Mandin Date: Tue, 10 Jan 2012 21:12:45 +0100 Subject: [PATCH] Add and use SuperToUser macro to handle super->user mode switch --- src/audio/mint/SDL_mintaudio_stfa.c | 9 ++-- src/audio/mint/SDL_mintaudio_xbios.c | 3 +- src/timer/mint/SDL_systimer.c | 10 ++-- src/video/ataricommon/SDL_atarisuper.h | 61 +++++++++++++++++++++++++ src/video/ataricommon/SDL_xbiosevents.c | 5 +- 5 files changed, 77 insertions(+), 11 deletions(-) create mode 100644 src/video/ataricommon/SDL_atarisuper.h diff --git a/src/audio/mint/SDL_mintaudio_stfa.c b/src/audio/mint/SDL_mintaudio_stfa.c index 50bd0eb50..4a581e035 100644 --- a/src/audio/mint/SDL_mintaudio_stfa.c +++ b/src/audio/mint/SDL_mintaudio_stfa.c @@ -38,6 +38,7 @@ #include "../SDL_sysaudio.h" #include "../../video/ataricommon/SDL_atarimxalloc_c.h" +#include "../../video/ataricommon/SDL_atarisuper.h" #include "SDL_mintaudio.h" #include "SDL_mintaudio_stfa.h" @@ -164,7 +165,7 @@ static void Mint_LockAudio(_THIS) /* Stop replay */ oldpile=(void *)Super(0); cookie_stfa->sound_enable=STFA_PLAY_DISABLE; - Super(oldpile); + SuperToUser(oldpile); } static void Mint_UnlockAudio(_THIS) @@ -174,7 +175,7 @@ static void Mint_UnlockAudio(_THIS) /* Restart replay */ oldpile=(void *)Super(0); cookie_stfa->sound_enable=STFA_PLAY_ENABLE|STFA_PLAY_REPEAT; - Super(oldpile); + SuperToUser(oldpile); } static void Mint_CloseAudio(_THIS) @@ -184,7 +185,7 @@ static void Mint_CloseAudio(_THIS) /* Stop replay */ oldpile=(void *)Super(0); cookie_stfa->sound_enable=STFA_PLAY_DISABLE; - Super(oldpile); + SuperToUser(oldpile); /* Wait if currently playing sound */ while (SDL_MintAudio_mutex != 0) { @@ -283,7 +284,7 @@ static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) /* Restart replay */ cookie_stfa->sound_enable=STFA_PLAY_ENABLE|STFA_PLAY_REPEAT; - Super(oldpile); + SuperToUser(oldpile); DEBUG_PRINT((DEBUG_NAME "hardware initialized\n")); } diff --git a/src/audio/mint/SDL_mintaudio_xbios.c b/src/audio/mint/SDL_mintaudio_xbios.c index dc82209e4..42a0d4a2f 100644 --- a/src/audio/mint/SDL_mintaudio_xbios.c +++ b/src/audio/mint/SDL_mintaudio_xbios.c @@ -41,6 +41,7 @@ #include "../SDL_sysaudio.h" #include "../../video/ataricommon/SDL_atarimxalloc_c.h" +#include "../../video/ataricommon/SDL_atarisuper.h" #include "SDL_mintaudio.h" #include "SDL_mintaudio_dma8.h" @@ -258,7 +259,7 @@ static void Devconnect2(int src, int dst, int sclk, int pre) DMAAUDIO_IO.dest_ctrl = dest_ctrl; DMAAUDIO_IO.sync_div = sync_div; - Super(oldstack); + SuperToUser(oldstack); } static void Mint_CheckExternalClock(_THIS) diff --git a/src/timer/mint/SDL_systimer.c b/src/timer/mint/SDL_systimer.c index 86344d944..01e7a410c 100644 --- a/src/timer/mint/SDL_systimer.c +++ b/src/timer/mint/SDL_systimer.c @@ -46,6 +46,8 @@ #include "../SDL_timer_c.h" #include "SDL_thread.h" +#include "../../video/ataricommon/SDL_atarisuper.h" + #include "SDL_vbltimer_s.h" /* from audio/mint */ @@ -64,7 +66,7 @@ void SDL_StartTicks(void) /* Set first ticks value */ old_stack = (void *)Super(0); start = *((volatile long *)_hz_200); - Super(old_stack); + SuperToUser(old_stack); start *= 5; /* One _hz_200 tic is 5ms */ @@ -80,7 +82,7 @@ Uint32 SDL_GetTicks (void) } else { void *old_stack = (void *)Super(0); now = *((volatile long *)_hz_200); - Super(old_stack); + SuperToUser(old_stack); } return((now*5)-start); @@ -111,7 +113,7 @@ int SDL_SYS_TimerInit(void) /* Install RunTimer in vbl vector */ old_stack = (void *)Super(0); timer_installed = !SDL_AtariVblInstall(SDL_ThreadedTimerCheck); - Super(old_stack); + SuperToUser(old_stack); if (!timer_installed) { return(-1); @@ -127,7 +129,7 @@ void SDL_SYS_TimerQuit(void) if (timer_installed) { void *old_stack = (void *)Super(0); SDL_AtariVblUninstall(SDL_ThreadedTimerCheck); - Super(old_stack); + SuperToUser(old_stack); timer_installed = SDL_FALSE; } read_hz200_from_vbl = SDL_FALSE; diff --git a/src/video/ataricommon/SDL_atarisuper.h b/src/video/ataricommon/SDL_atarisuper.h new file mode 100644 index 000000000..8f25c7e5f --- /dev/null +++ b/src/video/ataricommon/SDL_atarisuper.h @@ -0,0 +1,61 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _ATARI_SUPER_h +#define _ATARI_SUPER_h + +#include "SDL_stdinc.h" + +#ifndef SuperToUser + +/* + * Safe binding to switch back from supervisor to user mode. + * On TOS or EmuTOS, if the stack pointer has changed between Super(0) + * and Super(oldssp), the resulting user stack pointer is wrong. + * This bug does not occur with FreeMiNT. + * So the safe way to return from supervisor to user mode is to backup + * the stack pointer then restore it after the trap. + * Sometimes, GCC optimizes the stack usage, so this matters. + */ +#define SuperToUser(ptr) \ +(void)__extension__ \ +({ \ + register long retvalue __asm__("d0"); \ + register long sp_backup; \ + \ + __asm__ volatile \ + ( \ + "movl sp,%1\n\t" \ + "movl %2,sp@-\n\t" \ + "movw #0x20,sp@-\n\t" \ + "trap #1\n\t" \ + "movl %1,sp\n\t" \ + : "=r"(retvalue), "=&r"(sp_backup) /* outputs */ \ + : "g"((long)(ptr)) /* inputs */ \ + : "d1", "d2", "a0", "a1", "a2" \ + ); \ +}) + +#endif /* SuperToUser */ + +#endif /* _ATARI_SUPER_h */ diff --git a/src/video/ataricommon/SDL_xbiosevents.c b/src/video/ataricommon/SDL_xbiosevents.c index 1ef5ac1a4..232500f7a 100644 --- a/src/video/ataricommon/SDL_xbiosevents.c +++ b/src/video/ataricommon/SDL_xbiosevents.c @@ -30,6 +30,7 @@ #include #include "../../events/SDL_events_c.h" +#include "SDL_atarisuper.h" #include "SDL_xbiosevents_c.h" #include "SDL_xbiosinterrupt_s.h" @@ -75,7 +76,7 @@ void SDL_AtariXbios_InstallVectors(int vectors_mask) ); /* Back to user mode */ - Super(oldpile); + SuperToUser(oldpile); SDL_AtariXbios_enabled=1; } @@ -98,7 +99,7 @@ void SDL_AtariXbios_RestoreVectors(void) SDL_AtariXbios_Restore(kbdvecs); /* Back to user mode */ - Super(oldpile); + SuperToUser(oldpile); } static int atari_GetButton(int button)