summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrice Mandin <patmandin@gmail.com>2012-01-10 21:12:45 +0100
committerPatrice Mandin <patmandin@gmail.com>2012-01-10 21:12:45 +0100
commit77fbbe5c16c2eb911ae1e7d41fcd026fd00bd1b5 (patch)
treeb2a916ad5da1d48d911f5d900efa0a312ba9eb32
parentbee51f9a601896e8d32331708f0d5b8f062d4417 (diff)
downloadsdl-77fbbe5c16c2eb911ae1e7d41fcd026fd00bd1b5.tar.gz
Add and use SuperToUser macro to handle super->user mode switch
-rw-r--r--src/audio/mint/SDL_mintaudio_stfa.c9
-rw-r--r--src/audio/mint/SDL_mintaudio_xbios.c3
-rw-r--r--src/timer/mint/SDL_systimer.c10
-rw-r--r--src/video/ataricommon/SDL_atarisuper.h61
-rw-r--r--src/video/ataricommon/SDL_xbiosevents.c5
5 files changed, 77 insertions, 11 deletions
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 <mint/osbind.h>
#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)